我想学习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
功能是不允许修改主要明确分配的内存。 是对的吗? 为什么我不能只是free
我分配的内存main
在另一个函数? (并且这种行为在某种程度上具体到主?)
每当你传递参数给一个函数,一份拷贝,并且功能适用于该副本。 所以你的情况,你想free
原来的对象,这没有任何意义的副本。
你应该修改你的函数取一个指针,然后你可以把它称之为free
直接在该指针。
这是由值,这意味着创建副本,从而试图释放内存,其中局部变量传递entry
所在。 请注意, entry
与它所驻留在你的程序超出范围会自动被自动存储时间和内存对象destroyEntry
功能。
void destroyEntry(Entry entry)
{
Entry *entry_ptr = &entry;
free(entry_ptr);
return;
}
你的函数应该采取一个指针(引用传递):
void destroyEntry(Entry *entry)
{
free(entry);
}
然后,而不是destroyEntry(*(apple));
你只需要调用destroyEntry(apple);
。 请注意,如果没有与连接没有其他功能destroyEntry
功能,它是多余的,它是更好的只是直接致电free(apple)
。
这里的其他答案指出的主要问题 - 因为你提领你的苹果,当你调用destroyEntry在main(),它通过引用,创建副本。
甚至有一次,你知道你的问题,它有助于回到错误并尝试你看到哪些问题的文字连接,以便下一次的时候,您可能更容易快速地弄明白。 我发现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 -运行到指针相关的错误时,请尝试打印地址或喜爱的调试找到他们。 它通常至少指向你在正确的方向。
这一切都不是阻止张贴在堆栈交流你的问题,当然。 数以百计的程序员可能会从你已经这样做获益。