我的代码中是否有内存泄漏? (使用指针存储字符串)

时间:2012-06-17 00:29:39

标签: c string pointers memory-leaks

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

int main(void) {
    int x;
    int *in, *begin;
    in = (int *)malloc(sizeof(int));
    begin = in;
    while ((x = getchar()) != EOF) {
        *in = x;
        in++;
        in = (int *)malloc(sizeof(int));
    }
    *in = EOF;
    while ((x = *begin) != EOF) {
        putchar(x);
        begin++;
    }
    free(in);
    return 0;
}

我怀疑它确实存在。

使用这个程序,我试图使用指针将不定大小的用户输入存储到内存中,而不是使用char string[255]; fgets(string, sizeof(string));等。

编辑:当我运行程序时,程序没有崩溃或任何事情,我只是感觉有分配的内存没有被释放。

5 个答案:

答案 0 :(得分:2)

是的,程序有内存泄漏。

int *in, *begin;
in = (int *)malloc(sizeof(int));  /* allocate space for 1 int, at location "X" */
begin = in;
while ((x = getchar()) != EOF) {
    *in = x; 
    in++;    /* "in" increments address (to location) "X+1" */
    in = (int *)malloc(sizeof(int)); /* address "X+1" is lost as malloc returns  
                                        a different memory location, *not*
                                        necessarily at "X+2". Access to 
                                        previous data other than pointed to by 
                                        "begin" is lost */
}

*in = '\0';  /* this makes probably more senese than assigining EOF here */

分配内存时,需要对free()进行相应的调用。

另外,我认为输入没有正确存储。

in 永远不会给出 连续 内存块来存储数据。而是重复分配存储int的单个内存位置并将其分配给in,但我们并不知道这个内存在哪里,因此所有这些分配都丢失了,因为只有一个指针in正在跟踪它们。

换句话说,泄漏包括重复分配int大小的内存,将其分配给in,然后在下一次循环中丢失对该位置的任何引用。

变量begin最初指向输入的第一个项目,但随后在输出循环中重复递增1,因此随后会捕获未知内存。

更好的方法是在开始时分配一个更大的连续缓冲区,然后在递增in指针时使用它,或者以较小的数量开始但是然后根据需要更多地监视内存使用和realloc()(但需要更多的开销来保存一些内存的脚本)。

此外,在第一个循环结束时,而不是将EOF分配给in,放入一个空字符会更有意义。

最后,程序底部的free(in)调用只释放一个内存位置,而不释放以前分配的其他内存。

这是一个快速整合的版本,我尝试对原始代码进行微小更改保持代码结构完整(我相信你已经拥有了以这种方式编写它的原因首先是两个循环)尽管只用一个循环就可以写得更紧凑。

注意我最初为100个字符分配空间,根据您的需要调整它,或者最初分配较少,但随后跟踪内存消耗并根据需要跟踪realloc()更多内存(我认为这是您的初始值)意图,但没有正确实施。)

int main(void) {
    int x;
    int *in, *begin;
    int *start_loc;
    in = (int *)malloc(sizeof(int) * 100); /* continious space */
    begin = in;
    start_loc = in; /* keep track of start location for final free() call */

    while ((x = getchar()) != EOF) {
        *in = x;
        in++;
    }
    *in = 0;  /* terminator for the input string/data */

    while (*begin != 0) {   /* simplified */
        putchar(*begin);
        begin++;
    }

    free(start_loc);  /* free allocated memory */
    return 0;
}

这可以在不使用新变量start_loc的情况下编写(例如重用in),但我选择以这种方式编写它以强调跟踪你的开始的重要性内存分配和正确释放内存分配的能力,以解决内存泄漏问题。

答案 1 :(得分:1)

当然存在内存泄漏,对于malloc的每次调用,都会在您的程序中对free进行相应的调用。

在您的计划中malloc被多次调用,但只有一次调用free

答案 2 :(得分:1)

Levon的回答是正确的。您在此处增加了in的值:

in++;

...但是你将它重新分配给一个任意的地址:

in = (int *)malloc(sizeof(int));

要实现您想要做的事情,您需要:

  • 一次性分配大量连续内存,并在需要扩展时重新分配(这是您要实现的目标),或者;
  • 使用链接列表浏览非连续内存地址列表(这是您实际设法编写的内容)。

答案 3 :(得分:1)

是的,你有。 Free将为仅一个整数释放内存。您必须为每次free来电致电malloc

另外,要将字符存储在连续缓冲区中,您必须在开始时malloc一定量的内存,如果您读取的字符数超过最初分配的内存,则使用realloc

另外,不要忘记在字符串末尾为\0再分配一个字符。

完成后,您可以致电free(buffer)并成功!没有内存泄漏!

它的代码:

/* Start with an initial size */
int size = 128;
char *buffer = (char *)malloc(size + 1);
int i = 0;
while ((x = getchar()) != EOF) {
        buffer[i] = x;
        i++;
        if(i == size){
           /*Do realloc and increase size */
        }
}
buffer[i] = '\0';
/* Do what you want with buffer */
free(buffer);

答案 4 :(得分:0)

使用malloc分配内存时,应确保指向内存的指针不为NULL,释放内存后,最好将指针设置为NULL