在现有变量上调用malloc时会发生什么?

The*_*nus 5 c memory-management

如果变量已经malloc过去,那么如果malloc再次调用它而不是realloc?它会导致内存泄漏吗?

我想知道,以便我可以在malloc调用传递给函数的参数之前添加检查,以避免潜在的泄漏.

void memtest(char **foo)
{
        if ( foo )
                *foo = malloc(10); // Assuming *foo was already allocated in the past.
}
Run Code Online (Sandbox Code Playgroud)

我应该总是做以下事吗?

void memtest(char **foo)
{
        if ( foo ) {
                if ( *foo ) {
                        free(*foo);

                        *foo = NULL;
                }

                *foo = malloc(10);
        }
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*ler 5

如果指针*foo包含指向先前分配的内存的唯一指针,那么你刚刚泄漏了之前存在的内存.否则,它是完全无害的.


ric*_*ici 5

呼吁malloc无关紧要.

如果出现问题,问题是分配.在您完成之后,无论它有多重要,x=42;之前的值x都消失了.同样,如果foo你是某个内存的唯一指针,如果你覆盖foo,你就不能再访问那个内存了.

如果free不指定要释放的内容,则无法拨打电话.因此,如果你在失去唯一指针之前没有释放内存,那么你就无法释放它,这就是内存泄漏的定义.


use*_*751 5

没有"呼唤malloc变量"之类的东西.

malloc找到一些"自由"内存,将其标记为"已使用",并返回刚刚找到的内存开头的地址.free将一些"使用过的"记忆标记为"免费".

当你跑步

*foo = malloc(10);
Run Code Online (Sandbox Code Playgroud)

发生以下情况:

  • malloc 找到10个字节的可用内存.
  • malloc 标记使用的那10个字节.
  • malloc 返回刚刚找到的10个字节的起始地址.
  • 你的程序查看的值是foo,这是一个地址,因为它foo是一个指针.
  • 您的程序将malloc返回的地址存储在存储的地址中foo.

malloc不能不关心你的程序对它返回的地址做了什么.它不关心你的程序是将它存储在一个简单的变量,一个数组,另一个malloced空间,还是将它写入一个文件.它甚至不关心你的程序忘记了地址,但你应该关心,因为free如果程序不知道它试图释放的内存的地址,你的程序将永远无法调用.

有了这些知识,你应该能够看到这段代码的作用:

char *bar;
bar = malloc(10);
bar = malloc(10);
free(bar);
Run Code Online (Sandbox Code Playgroud)

花点时间弄清楚,然后阅读下面的内容:

 

 

  • bar声明了一个变量.它的类型是char*.
  • 该程序调用malloc.
  • malloc 找到10个空闲字节并将其标记为已使用.
  • malloc 返回10个字节的起始地址.
  • 程序存储地址bar.(bar现在包含前10个字节的地址)
  • 该程序调用malloc.
  • malloc 找到10个更多的空闲字节并将它们标记为已使用.
  • malloc 返回10个字节的起始地址.
  • 程序存储地址bar.(bar现在包含第二个10字节的地址)
  • 程序调用free并传递第二个10字节开头的地址.
  • free 将第二个10个字节标记为空闲.

这是内存泄漏.永远不会释放前10个字节.我可以告诉他们永远不会被释放,因为程序不知道他们在哪个地址.

但是这个节目怎么样?

char *bar;
char *baz;
bar = malloc(10);

baz = bar;
baz = malloc(10);
Run Code Online (Sandbox Code Playgroud)

在这里,我称之为malloc"on"一个已经拥有malloced 的地址的变量.这是内存泄漏吗?不是单独的.程序可能仍然free是第一个存储块,其地址仍然存储在其中baz.

但是,这肯定是内存泄漏:

void func()
{
    char *bar;
    char *baz;
    bar = malloc(10);

    baz = bar;
    baz = malloc(10);
}
Run Code Online (Sandbox Code Playgroud)

我甚至没有改变代码,但只是把它放在一个函数中,它现在是一个内存泄漏!Whaaaaaaaaa?

记住内存泄漏究竟是什么.内存泄漏是指程序分配内存但从不释放内存.您无法通过查看malloc调用来判断程序是否释放了所有内存.


至于第二部分 - "我应该这样做吗?"

不,你不应该.

仅当传递给您的函数的地址的旧值是malloced指针,并且调用者忘记了free它时,它才会起作用.

您的建议将破坏以下任何功能:

void func1()
{
    char c;
    char *ptr = &c;
    memtest(&ptr); // Tries to free something that wasn't malloced!
    // ... do something with ptr ...
}
void func2()
{
    char *ptr;
    memtest(&ptr); // Passes a garbage address to free!
    // ... do something with ptr ...
}
void func3()
{
    char *ptr1 = malloc(5)
    char *ptr2 = ptr1;
    memtest(&ptr1);
    // ... do something with ptr1 and ptr2 ...
    free(ptr1); // Frees memory that was already freed!
}
Run Code Online (Sandbox Code Playgroud)

总之:标题中的问题没有意义.检测内存泄漏并不像这样简单.而你想要做的是一个坏主意.