malloc()在free()之后重复使用内存位置,导致碎片化。

3

好的,我已经花费了很多精力,在这里查看了很多问题,但是我还无法完全解决这个问题。希望您能在这里为我的问题提供一些帮助!

int main(int argc, char *argv[]){

  char read[50]; 
  char *string[10];

  while(1){

    fgets(read,sizeof read, stdin);

    int t = 0; //ticks whenever a non-whitespace char is read 
    int pos = 0; //keeps track of position in string array 
    int i;
    int j;

    for(i = 0; i < sizeof read; i++){
      if(isspace(read[i]) && t != 0){
        string[pos] = malloc((t+1) * (sizeof(char)));
//      int z;
//      for(z = 0; z < sizeof string[pos]; z++){
//        string[pos][z] = '\0';
//      }
        for(j = 0; j < t; j++){
          string[pos][j] = read[i-(t-j)];
        }
        t = 0;
        pos++;
      }
      else if(!isspace(input[i])) t++;
    }

    int k;
    for(k = 0; k < pos; k++){
      printf("%i: %s\n",k,string[k]);
      free(string[k]);
    }
  }
}

我正在尝试编写一个程序,该程序将从用户那里读取一个句子,然后将其分解成单独的单词,并将每个单词存储在自己的char数组中。

我使用malloc()来分配足够的内存来容纳每个单词,并在使用后释放它。

第一次运行很好,但在随后的循环中,长度小于5个字符的单词(仅当输入多个由空格分隔的单词时)将不能正确显示,会附加一些随机的额外字符/符号。

这可能是由于malloc使用了未清空的已释放内存引起的吗?如果是这种情况,我应该如何正确使用malloc?

我发现唯一的解决方法是使用我已经注释掉的代码。它用\0填充新分配的char数组。

谢谢!

示例输出:

input words(0): we we we   
0: we
1: we
2: we

input words(1): we we we 
0: we�
1: we�
2: we

这里calloc函数不是一个有用的函数吗?https://dev59.com/1XI_5IYBdhLWcg3wEexu - Tony Suffolk 66
是的,malloc 会尽可能地重复使用内存,以提高缓存友好性。 - o11c
似乎如果我不立即填充整个数组,calloc()可能会有用- 在我的情况下,清零最后一个字节似乎解决了我的问题! - Hal
这里似乎有些不对劲。free(pointer)应该立即将内存返回给操作系统... - FlyingGuy
如果你知道自己在做什么,使用malloc是完全可以的。C语言没有垃圾回收机制,它会按照你的要求执行。如果你在失去指针之前没有释放malloc分配的内存,就会出现内存泄漏。同样地,如果你在使用该内存之前就释放了malloc分配的内存,最好的情况是出现段错误,最坏的情况是内核崩溃。 - FlyingGuy
2个回答

6
你有两个问题:
1) 这里在使用条件语句中使用了 sizeof read:

for(i = 0; i < sizeof read; i++){

如果输入行不像sizeof read那么长,你应该在这里使用strlen(read)
2) 虽然你为字符串分配了足够的内存,但你没有以0结尾。你可以使用calloc()将整个内存清零。由于你立即写入它们,我更喜欢使用malloc()而不是需要用calloc()不必要地清零,并在循环后立即用0终止字符串:
    for(j = 0; j < t; j++){
      string[pos][j] = read[i-(t-j)];
    }
    string[pos][j] = 0; // 0 terminates the string.

P.S.: sizeof(char) 总是为1。


太棒了,终止字符串似乎解决了问题!关于strlen()的提示也很不错,我会利用它的。谢谢! - Hal

1

你永远不应该假设malloc分配给你的内存为零。

所有(C风格)字符串都应以值为0的尾随字符结尾,如果不这样做,将获得未定义的行为。

在未定义行为的领域,结果是未定义的! 也就是说编译器可以自由地执行任何操作。

避免未定义行为。


谢谢,我不知道 malloc() 有这种行为,知道这点非常有用。 - Hal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接