在不同的function分配的空闲内存?
我试图学习C和我目前正在尝试编写一个基本的堆栈数据结构,但我似乎无法获得基本的malloc
/ free
权利。
这里是我一直在使用的代码(我只是在这里发表一小部分来说明一个特定的问题,而不是总代码,但是错误信息是通过在valgrind
运行这个示例代码来生成的)
#include <stdio.h> #include <stdlib.h> typedef struct Entry { struct Entry *previous; int value; } Entry; void destroyEntry(Entry entry); int main(int argc, char *argv[]) { Entry* apple; apple = malloc(sizeof(Entry)); destroyEntry(*(apple)); return 0; } void destroyEntry(Entry entry) { Entry *entry_ptr = &entry; free(entry_ptr); return; }
当我通过valgrind
运行--leak-check=full --track-origins=yes
,出现以下错误:
==20674== Invalid free() / delete / delete[] / realloc() ==20674== at 0x4028E58: free (vg_replace_malloc.c:427) ==20674== by 0x80485B2: destroyEntry (testing.c:53) ==20674== by 0x8048477: main (testing.c:26) ==20674== Address 0xbecc0070 is on thread 1's stack
我认为这个错误意味着destroyEntry
函数不允许修改在main中显式分配的内存。 是对的吗? 为什么我不能只free
我在另一个函数中分配的内存? (这种行为有点特定于主?)
无论何时将parameter passing给某个函数,都会创build一个副本,并且该函数将在该副本上工作。 所以在你的情况下,你试图free
一个原始对象的副本,这是没有任何意义的。
你应该修改你的函数来获取指针,然后你可以直接在指针上调用它。
这是通过值传递,这意味着复制已创build,因此您尝试释放内存,其中本地variablesentry
驻留。 请注意,当你的程序超出了destroyEntry
函数的范围时, entry
是一个具有自动存储持续时间和内存驻留的对象将被自动释放。
void destroyEntry(Entry entry) { Entry *entry_ptr = &entry; free(entry_ptr); return; }
你的函数应该带一个指针(通过引用传递):
void destroyEntry(Entry *entry) { free(entry); }
然后,而不是destroyEntry(*(apple));
你只需要调用destroyEntry(apple);
。 请注意,如果没有与destroyEntry
函数相关的其他function,则它是多余的,最好直接调用free(apple)
。
这里的其他答案指出了主要的问题 – 因为当你调用main()中的destroyEntry时,你引用你的苹果,它通过引用传递,创build一个副本。
即使一旦你知道自己的问题,这有助于回到错误,并尝试连接你所看到的问题的文本,以便下一次出现时,你可能会更快地弄清楚。 我发现C和C ++错误有时可能看起来很模糊。
一般来说,当我无法释放指针或删除对象时,我喜欢打印出地址,特别是当我分配地址的时候,当我试图释放地址的时候。 valgrind已经给了你不好的指针的地址,但它有助于比较它的好。
int main() { Entry * apple; apple = malloc(sizeof(Entry)); printf("apple's address = %p", apple); // Prints the address of 'apple' free(apple); // You know this will work }
这样做之后,你会注意到printf()语句给了你一个像0x8024712这样的地址(只是在一般范围内构成一个地址),但是你的valgrind输出给了0x4028E58。 你会注意到它们在两个完全不同的地方(事实上,“0x4 …”在堆栈中,而不是malloc()从中分配的堆,但是我假设你刚开始是这样的不是你的红旗),所以你知道你试图从错误的地方释放记忆,因此“无效的免费()”。
所以从那里你可以对自己说:“好吧,不知怎的,我的指针正在被损坏。” 你已经把你的问题归结为一个小的,可编辑的例子,所以它不会花你很长的时间来解决这个问题。
TL; DR – 当遇到与指针相关的错误时,尝试打印地址或在您喜欢的debugging器中find它们。 它往往至less指出你在正确的方向。
当然,这些都不妨碍在Stack Exchange上发布你的问题。 数百名程序员可能会从中受益。