char *t = malloc(2);
t = "as";
t = realloc(t,sizeof(char)*6);
我收到错误“无效指针:0x080488d4 * ”..
我在使用内存分配功能时遇到了奇怪的错误。是否有任何好的tuts /指南可以解释我的内存分配功能。 我正在使用linux ..
请帮助..
答案 0 :(得分:5)
这是你的问题:
char *t = malloc(2);
t = "as";
您可能认为这会将两个字符的字符串"as"
复制到刚刚分配的缓冲区中。它实际上做的是扔掉(泄漏)缓冲区,并将指针更改为指向字符串常量 "as"
,它存储在机器代码旁边的只读存储器中,而不是malloc
堆上。因为它不在堆上,realloc
查看指针并说“不能做,那不是我的”。 (通过向您提供此错误,计算机对您很好;当您向realloc
提供未由malloc
或realloc
返回的指针时,计算机可以让恶魔飞行如果它想要你的鼻子。)
这是如何做你想做的事情:
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