使用realloc进行动态内存分配

时间:2009-10-28 11:46:40

标签: c++ memory-leaks memory-management

我正在学习C ++。我正在尝试学习这种动态内存分配。在下面的代码中,我尝试使用mallocrealloc分配内存。

int main (void)  {
  char *g = (char*) malloc (sizeof(char) * 2);
  g = "ab";
  g = (char*) realloc (g, sizeof(char) * 200);
  strcpy (g, "cdefg");
  cout << g << endl;
  return 0;
}

执行此代码时出现分段错误错误。

我已经看到其他SO主题建议使用vectornew而不是使用上述方法。因为,我正在尝试学习这种方法,所以这些答案不适用于我的问题。

我遇到过这种方法很合适的场景,例如,如果我正在使用ifstream.read函数读取原始文本文件并阅读,那么就说1024字节。现在,如果我想确保我没有读到因1024字节大小而被破坏的单词,我必须使用ifstream.get从该位置进一步阅读,直到找到空格字符。在这种情况下,我需要稍微调整缓冲区(1024)。我的意图是在这里使用realloc为它分配更多的内存。

如果我在任何地方都错了,请随时纠正我。

5 个答案:

答案 0 :(得分:9)

g = "ab";

你使g指向位于静态存储中的块,而不是堆上的块,然后在

g = (char*) realloc (g, sizeof(char) * 200); 

您尝试使用属于堆外的地址调用realloc()。这是未定义的行为并导致程序崩溃。您只能使用realloc()malloc()(或空指针)返回的地址来调用realloc()

问题在于你的意思是:

strcpy( g, "ab" ); 

但错误地写了这个:

g = "ab";

前者可以正常工作 - g最初设置为malloc()返回的地址。

还有一个问题 - 你最初分配的内存太少了。您应该为null终止符分配一个额外的字节。

答案 1 :(得分:7)

您的代码存在许多问题。首先,如果您使用C ++进行编程,则不应使用malloc和朋友。

char *g = (char*) malloc (sizeof(char) * 2);
g = "ab";

糟糕!您刚刚丢失了malloc调用返回的2个字节的内存,因为现在g指向可能只读存储"ab"的位置。

g = (char*) realloc (g, sizeof(char) * 200);

realloc只能在之前的malloc返回的指针上调用。

即使您已将有效指针传递给realloc,如果重新分配失败,realloc也可能返回NULL。在这种情况下,先前分配的内存仍然会被分配,但是您将覆盖指向该内存的唯一变量,从而无法释放先前的分配。请参阅C FAQ列表中的Having dynamically allocated an array, can I change its size?

另请注意,"ab"需要三个字节的存储空间,而不是两个字节。最后,sizeof(char)始终在任何地方1,因此您无需在sizeof(char)来电中使用malloc

程序的正确 C 版本如下所示:

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

int main (void)  {
    char *tmp;
    char *g = malloc(3);
    if ( !g ) {
        return EXIT_FAILURE;
    }

    strcpy(g, "ab");

    tmp = realloc (g, 200);
    if ( !tmp ) {
        return EXIT_FAILURE;
    }
    g = tmp;

    strcpy (g, "cdefg");
    puts(g);
    return 0;
}

在C ++版本中,您将使用string而不是规划旧的C样式字符数组。

有关如何重新分配缓冲区以阅读问题第二部分的完整行的示例,请参阅my answer to another question

但请注意,代码也是 C ,我相信有更好的方法可以在C ++中执行您想要的操作。我只是不太了解C ++标准库,无法为您提供正确的C ++解决方案。

答案 2 :(得分:3)

问题是该行:

g = "ab";

g指针设置为另一个位置。它不会复制内容。您忘记了原始位置,当您在g中使用realloc时,您将realloc错误的指针。

将该行替换为:

strcpy(g, "ab");

当然,您需要三个字节来存储字符串和终止'\0'字符。

那就是说,mallocrealloc是C风格的东西。如果您使用的是C ++,则应尝试newdelete,并可能使用string类型来存储字符串。

答案 3 :(得分:2)

您需要将原始malloc增加到3以包含null终止符,并使用strcpy将内容设置为“ab”

char *g = (char*) malloc (sizeof(char) * 3);
strcpy(g , "ab");

答案 4 :(得分:0)

问题的第二部分:

考虑使用std::vector

std::vector<char> g;
g.resize(1024);
// fill up g
// decide you need another hundred bytes at the end of g
g.resize(1124);
// memory will automatically be released when g goes out of scope

请注意,要将指针传递到缓冲区的开头,您现在必须说&g[0]而不是简单地g