我正在学习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;
}
执行此代码时出现分段错误错误。
我已经看到其他SO主题建议使用vector
或new
而不是使用上述方法。因为,我正在尝试学习这种方法,所以这些答案不适用于我的问题。
我遇到过这种方法很合适的场景,例如,如果我正在使用ifstream.read
函数读取原始文本文件并阅读,那么就说1024字节。现在,如果我想确保我没有读到因1024字节大小而被破坏的单词,我必须使用ifstream.get
从该位置进一步阅读,直到找到空格字符。在这种情况下,我需要稍微调整缓冲区(1024)。我的意图是在这里使用realloc
为它分配更多的内存。
如果我在任何地方都错了,请随时纠正我。
答案 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'
字符。
那就是说,malloc
和realloc
是C风格的东西。如果您使用的是C ++,则应尝试new
和delete
,并可能使用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
。