3

假设我的程序中有以下代码:

char *ptr;
ptr=malloc(sizeof(char)*10);
ptr=malloc(sizeof(char)*10);
ptr=malloc(sizeof(char)*10);
ptr=malloc(sizeof(char)*10);

每次都会分配指向同一内存块的指针ptr,还是每次都保留一块单独的内存并将其分配给的指针ptr,导致每次malloc()调用内存泄漏?

我仍在学习 C,如果它太基础,请多多包涵。我尝试谷歌搜索,但没有找到答案。

编辑::

感谢您的回答。请告诉我我的这种方法是否处理内存泄漏风险。我的程序只是询问 5 个人的姓名并显示它,而不使用静态数组。阅读您的答案后,我将free(ptr)循环放入,否则在我计划只在循环外使用一次之前,在循环之后。我现在正确吗?

#include <stdio.h>
#include<stdlib.h>
#include<string.h>

int main ()
{
char *names[5],*ptr;
int i;

for(i=0;i<=4;i++)
{
    ptr=malloc(sizeof(char)*10);
    printf("Enter name no.%d : \n",i+1);
    scanf("%s",ptr);
    names[i]=malloc(strlen(ptr)+1);
    strcpy(names[i],ptr);
    free(ptr);


}
for(i=0;i<=4;i++)
printf("%s\n",names[i]);

}
4

7 回答 7

6

malloc()永远不会多次返回相同的内存块,除非(当然)它free()自上次返回以来已被 'd 。这是由 C 标准保证的。因此,您的代码也会泄漏内存。任何两次分配同一块内存的内存分配器都会比无用更糟糕:应用程序会踩到自己的脚趾,可能同时将同一块内存用于不同的目的。

编辑:除非缓冲区溢出问题,您的代码是正确的,因为它释放了通过ptr. free(ptr)在循环外只调用一次确实是不正确的。但是,您的代码(如此处所示)不会释放稍后存储在names[i].

于 2013-05-13T14:52:59.507 回答
2

是的,每次malloc调用都会分配一个新块,这意味着前一个会被泄露。

编辑:回答问题的已编辑部分

您现在正确地释放了ptr指向的块,但是您没有释放分配给names. 您还需要:

for(i=0;i<=4;i++) {
   printf("%s\n",names[i]);
   free(names[i]);
}

在您的情况下,您可以跳过使用ptrnames直接进行操作。这是一个同样 [un] 安全的版本:

char *names[5];
int i;

for(i=0; i < 5; i++)
{
    names[i] = malloc(10);
    printf("Enter name no.%d : \n",i+1);
    scanf("%s",names[i]); // what if name is longer than 10 characters?
}

for(i=0; i < 5; i++)
{
   printf("%s\n",names[i]);
   free(names[i]);
}

但是,一旦进程退出,操作系统会回收进程消耗的内存,所以在这个简单的例子中你不必担心,但我想这只是一个例子。我还假设您不关心用户输入的名称超过 10 个字符,这会写入分配的缓冲区的边界。

于 2013-05-13T14:53:02.680 回答
2

每次都会分配一个单独的内存块,因为 C 不执行任何垃圾收集,并且free在调用之间不进行任何malloc调用。前三个块被泄露,因为您没有保留指向它们的指针。

printf您可以使用一个简单的调用自己发现指针都是不同的:

for (int i = 0; i < 4; i++) {
    ptr = malloc(10);     // no need for sizeof(char), it's 1 by definition
    printf("%p\n", ptr);
}

这应该打印四个不同的数字。

于 2013-05-13T14:53:18.023 回答
2

假设每次调用都成功,这将导致内存泄漏,除了分配给最后一个内存之外的所有内存malloc都将无法访问。您要么需要为pointer分配的每个块保留 a,要么malloc需要free在连续调用之间保留。所以是的,malloc将尝试为每个调用分配不同的内存块。快速测试可能如下:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char *ptr;
    ptr=malloc(sizeof(char)*10);
    printf("%p\n", ptr);
    ptr=malloc(sizeof(char)*10);
    printf("%p\n", ptr);
    ptr=malloc(sizeof(char)*10);
    printf("%p\n", ptr);
    ptr=malloc(sizeof(char)*10);
    printf("%p\n", ptr);
}

这将打印出每次分配的地址。如果你free在每次调用之间添加了一个,malloc你可能会得到相同的结果pointer,一个快速测试 证明了这种行为。

于 2013-05-13T14:53:39.030 回答
1

您的第二部分是正确的:这是内存泄漏。

于 2013-05-13T14:52:42.133 回答
1

每次调用 malloc 时都会分配一个新的内存块。这将造成内存泄漏,因为您无法引用前三个分配来释放它们。

于 2013-05-13T14:53:43.303 回答
1

您可以使用 valgrind 检查内存泄漏,它在检测内存泄漏方面非常有用。

valgrind ./progr
于 2013-05-13T15:17:13.670 回答