C语言 在不同函数中分配的可用内存



我正在尝试学习 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;
}

当我用--leak-check=full --track-origins=yes运行它时valgrind,我收到以下错误:

==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我在main中分配的内存到另一个函数中?(这种行为是否以某种方式特定于 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)

这里的其他答案指出了主要问题 - 因为当你在main()中调用destroyEntry时,你取消了对苹果的引用,它通过引用传递,创建一个副本。

即使你知道你的问题,回到错误并尝试将你所看到的文本与问题联系起来也会有所帮助,这样下次出现它时,你更有可能很快弄清楚。 我发现 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() 分配的堆上,但我假设如果你刚刚开始,这对你来说还不是一个危险信号),所以你知道你试图从错误的地方释放内存,因此"无效的free()"。

所以从那里你可以对自己说:"好吧,不知何故我的指针被损坏了。 您已经将问题归结为一个小的、可编译的示例,因此从那里解决它不会花费很长时间。

TL;DR - 遇到与指针相关的错误时,请尝试打印地址或在你喜欢的调试器中找到它们。 它通常至少会为你指明正确的方向。

当然,所有这些都不是为了阻止在Stack Exchange上发布您的问题。 数以百计的程序员可能会从你这样做中受益。

相关内容

  • 没有找到相关文章

最新更新