【问题标题】:Allocating memory for a dynamic list of strings [duplicate]为字符串的动态列表分配内存[重复]
【发布时间】:2018-03-18 22:26:00
【问题描述】:
int strings(void){
  int NumStrings = 3;
  char **strings = (char**) malloc(sizeof(char*) * NumStrings);
  int i;
  char * element = "Trevor";
  for(i = 0; i < NumStrings; i++){
     strings[i] = ((char*) malloc(sizeof(char) * strlen(element)+1));
  }
  strings[0] = "abcdef";
  strings[1] = "lemons";
  strings[2] = "zoozoo13333";
  for(i = 0; i < NumStrings; i++){
    printf("%s\n", strings[i]);
  }
}

为什么这不会导致段错误?我没有为“zoozoo13333”分配足够的内存,但它仍然可以正常打印,并且不会引发任何错误。数组中不应该只有足够的空间容纳 6 个字符长的字符串吗?

【问题讨论】:

  • 分配字符串字面量不需要任何内存分配。你实际上在这里泄漏了内存。也不要强制转换mallocsizeof(char) 的返回值总是1
  • 因为你没有缓冲区溢出,而是内存泄漏:strings[2] = "zoozoo13333"; 将丢弃分配内存的句柄并分配字符串字面量。

标签: c memory-management


【解决方案1】:

您没有遇到缓冲区溢出,因为您根本没有写入缓冲区。

strings[2] = "zoozoo13333";

不复制字符串,它只是将strings[2] 更改为指向字符串文字的内存,而不是您使用malloc() 分配的缓冲区。结果,您有内存泄漏,因为您已分配内存但没有任何指向它。

要复制字符串,您必须使用strcpy()。如果你这样做了,你会得到一个缓冲区溢出:

strcpy(strings[2], "zoozoo13333");

这会导致未定义的行为,因为您写入超出缓冲区的末尾。它不一定会导致分段错误。见Why don't I get a segmentation fault when I write beyond the end of an array?

【讨论】:

  • 我将 strcpy 添加到程序中,你是对的,即使我为 6 长度的字符串分配了足够的内存,它仍然会打印“zoozoo13333”。所以由我决定要添加到数组中的字符串的大小吗?有什么办法可以防止小于分配空间的字符串从开始允许添加到列表中?
  • 尝试将长字符串分配给strings[0] 而不是strings[2],我敢打赌你会注意到一些奇怪的事情。
  • 是的,C 不会自动检测越界写入。与其为所有缓冲区分配相同的大小,不如为每个缓冲区分配要复制到其中的字符串的大小。您也可以使用strdup() 函数,它会自动为您执行此操作。
  • 是的,我看到了问题所在。谢谢,它在最后添加了下一个元素......非常奇怪的行为。谢谢,我会研究这个功能。
【解决方案2】:

我没有为“zoozoo13333”分配足够的内存,但它仍然 打印正常,不会抛出任何错误。

您应该意识到,每当您执行"zoozoo13333" 之类的操作时,已经为这组字符分配了内存(以及尾随的\0)。但是,此内存恰好分配在您无法修改的区域中。换句话说,您不能更改此字符串本身。由于内存已分配(隐式)并且您的字符串有效,因此可以正常打印。

数组中不应该只有足够的空间容纳一个字符串吗? 6 个字符长?

现在,strings[i] 只是一个指向 char 的指针,仅此而已。执行此操作时,您正在正确地分配指向char 的指针:strings[2] = "zoozoo13333";。没有缓冲区溢出。如上所述,字符串的空间已经在其他地方留出。您失去的是使用malloc() 获得的分配空间的句柄。因此,您无法释放此空间,并且存在内存泄漏。

【讨论】:

    猜你喜欢
    • 2018-06-16
    • 2017-07-24
    • 2020-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多