使用realloc重新分配动态内存

lea*_*ner 2 c++ memory-leaks memory-management

我正在学习C++.我正在尝试学习这种动态内存分配.在下面的代码中,我试图使用malloc和分配内存realloc.

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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

sha*_*oth 9

g = "ab";
Run Code Online (Sandbox Code Playgroud)

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

g = (char*) realloc (g, sizeof(char) * 200); 
Run Code Online (Sandbox Code Playgroud)

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

问题是你这意味着:

strcpy( g, "ab" ); 
Run Code Online (Sandbox Code Playgroud)

但错误地写了这个:

g = "ab";
Run Code Online (Sandbox Code Playgroud)

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

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


Sin*_*nür 7

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

char *g = (char*) malloc (sizeof(char) * 2);
g = "ab";
Run Code Online (Sandbox Code Playgroud)

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

g = (char*) realloc (g, sizeof(char) * 200);
Run Code Online (Sandbox Code Playgroud)

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

即使您已经传递了有效指针realloc,realloc如果重新分配失败,也可能返回NULL.在这种情况下,先前分配的内存仍然会被分配,但是您将覆盖指向该内存的唯一变量,从而无法释放先前的分配.请参阅动态分配数组,我可以更改其大小吗?在C FAQ列表中.

另外,请注意,"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;
}
Run Code Online (Sandbox Code Playgroud)

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

有关如何重新分配缓冲区以读取问题第二部分的完整行的示例,请参阅我对另一个问题的回答.

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