繁体   English   中英

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

[英]What happens when you call malloc on an existing variable?

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

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

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

我应该总是做以下事吗?

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

                        *foo = NULL;
                }

                *foo = malloc(10);
        }
}

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

malloc的调用无关紧要。

如果出现问题,问题是分配。 你做x=42; 无论它有多重要, x的先前值都消失了。 类似地,如果foo是你必须拥有某个内存的唯一指针,如果你覆盖foo ,你将无法再访问该内存。

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

没有“在变量上调用malloc ”这样的东西。

malloc找到一些“free”内存,将其标记为“used”,并返回刚刚找到的内存开头的地址。 free标记一些“使用”的记忆为“免费”。

当你跑步

*foo = malloc(10);

发生以下情况:

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

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

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

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

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

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

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

但是这个节目怎么样?

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

baz = bar;
baz = malloc(10);

在这里,我将malloc称为“on”一个已经保存了malloc ed的地址的变量。 这是内存泄漏吗? 不是单独的。 程序可能仍然free第一个内存块,其地址仍然存储在baz

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

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

    baz = bar;
    baz = malloc(10);
}

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

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


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

,你不应该。

只有传递给你的函数的地址的旧值是一个malloc ed指针, 并且调用者忘记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!
}

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

它导致内存泄漏,因为先前分配的内存未被任何变量引用,并且您丢失了其地址。

没有具体的检查。 您可以在声明时将指针设置为NULL ,并在每次free内存时将其设置为NULL 然后你可以在调用malloc之前检查if (pointer == NULL)

使用realloc可以避免内存泄漏问题,因为如果指针是空指针,则realloc函数的行为类似于指定大小的malloc函数。 但如果未将指针声明设置为NULL则可能会导致问题。

即:

int *foo = NULL;

void bar( void )
{
     foo = realloc(foo, 10*sizeof(int));
}

realloc的一个好或坏特征是它保留了你记忆的内容。

我应该总是做以下事吗?

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

        *foo = malloc(10);
}

不,你不应该因为free而没有将指针设置为NULL并且如果你的指针仍然具有已经free ed内存的值,那么程序就会出错。 我的意思是,如果你在代码中的某个地方free指针而不重新分配它,这样的代码就容易出错。 并且您必须确保将指针声明为NULL作为初始值。

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

可能性很小:

  • 如果以前的malloc成功分配了内存,则重新分配内存将导致内存泄漏。
  • 如果无论如何通过前一个malloc调用的内存分配失败,那么就不会有内存泄漏。

我应该总是做以下事吗?

 void memtest(char **foo) { if ( *foo ) free(*foo); *foo = malloc(10); } 

是。 通过这种方式,您可以确保没有内存泄漏。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM