在C / C ++中使用realloc时出错

时间:2011-10-14 19:25:45

标签: c realloc

char *t = malloc(2);
t = "as";

t = realloc(t,sizeof(char)*6);

我收到错误“无效指针:0x080488d4 * ”..

我在使用内存分配功能时遇到了奇怪的错误。是否有任何好的tuts /指南可以解释我的内存分配功能。 我正在使用linux ..

请帮助..

5 个答案:

答案 0 :(得分:5)

这是你的问题:

char *t = malloc(2);
t = "as";

您可能认为这会将两个字符的字符串"as"复制到刚刚分配的缓冲区中。它实际上做的是扔掉(泄漏)缓冲区,并将指针更改为指向字符串常量 "as" ,它存储在机器代码旁边的只读存储器中,而不是malloc堆上。因为它不在堆上,realloc查看指针并说“不能做,那不是我的”。 (通过向您提供此错误,计算机对您很好;当您向realloc提供未由mallocrealloc返回的指针时,计算机可以让恶魔飞行如果它想要你的鼻子。)

这是如何做你想做的事情:

char *t = malloc(3);
strcpy(t, "as");

请注意,由于隐式NUL终结符,您需要三个字符而不是两个字符的空间。

顺便说一句,你永远不需要乘以sizeof(char);根据定义,它是1

答案 1 :(得分:3)

这不是你在C中分配字符串的方式。

正确的语法是:

char* t = malloc(3);  // Reserve enough space for the null-terminator \0

strncpy(t, "as", 3);
// Copy up to 3 bytes from static string "as" to char* t.
// By specifying a maximum of 3 bytes, prevent buffer-overruns

"as"分配2个字节是不够的 C字符串有一个1字节的空终止符,因此至少需要3个字节来保存"as\0"\0表示空终止符)

您编写的代码:t = "as";使指针t“放弃”以前分配的内存,而是指向静态字符串"as"。使用malloc分配的内存“泄露”并且无法恢复(直到程序终止并且操作系统回收它)。

在此之后,您可以像原先一样拨打realloc 但是,您应执行t = realloc(t,6);。如果realloc因任何原因失败,你就会失去记忆。

首选方法是:

new_t = realloc(t, 6);
if (new_t != NULL)  // realloc succeeded
{   t = new_t;  
}
else
{  // Error in reallocating, but at least t still points to good memory!
}

答案 2 :(得分:2)

您的代码重新分配t,使其指向其他地方

char *t = malloc(2); //t=0xf00ba12
t = "as"; //t=0xbeefbeef
t = realloc(t,sizeof(char)*6); //confused because t is 0xbeefbeef, not 0xf00b412.

而是使用strcpy

char *t = malloc(3); //don't forget about the '\0'
strcpy(t, "as");
t = realloc(t, 6); //now the string has room to breathe

答案 3 :(得分:0)

首先,不要这样做:

char *t = malloc(2);

请改为:

char *t = malloc(2 * sizeof(char));
/* or this: */
char *t = calloc(2, sizeof(char));

这可能看起来不值得,但是当你处理大于1个字节的类型时,你可能会遇到问题。

在这一行:

t = "as";

您正在分配字符串文字"as"的地址,因此您的指针不再指向您分配的内存。您需要将文字的内容复制到分配的内存中:

char *t = calloc(3, sizeof(char));
/* "ar" is 3 char's: 'a', 'r' and the terminating 0 byte. */
strncpy(t, "ar", 3);
/* then later: */
t = realloc(t,sizeof(char)*6);

你也可以使用更安全的strdup:

#include <string.h>

char *t = strdup("ar");
t = realloc(t,sizeof(char)*6);

不要忘记释放记忆

free(t);

答案 4 :(得分:0)

char *t = malloc(2);

这意味着您已经创建了一个指向可以容纳2个字节的内存位置的指针

     +-+-+ 
t -> | | |
     +-+-+ 

当你做

t = "as";

现在你指的是其他地方,而不是它最初所指向的地方。现在它不再指向堆

t = realloc(t,sizeof(char)*6);

现在你把指针指向只读内存并尝试重新分配它。

当你使用malloc时,你在堆上分配空间。在这种情况下,t是指向该位置的指针,即块所在的地址。

为了在那个地方放置一些东西,你需要通过解除引用来复制那里的数据,这是通过在t前面写*来完成的:

*t = 'a';   // now 'a' is where t points
*(t+1)='s'; // now 's' is behind a, t still pointing to 'a'

但是在C中,字符串总是以0(ASCII值)结尾写为'\ 0',所以为了使它成为一个字符串,你需要附加一个\ 0

     +-+-+--+ 
t -> |a|s|\0|
     +-+-+--+ 

为了做到这一点,你需要malloc 3个字节,而不是你可以通过写*(t+2)='\0';来添加\ 0

现在可以将t视为指向一个字符串,并在将字符串作为参数的函数中使用,例如strlen( t )返回2