我使用malloc获得了一些非常奇怪的行为。我从不分配超过4kB,所以这对我来说似乎特别奇怪。我的主要看起来像:
int main(int argc, char **argv)
{
char *buf;
char *raw = malloc(1024);
fgets(raw, 1024, stdin);
parse(raw, &buf); // Process raw input, get parse length
printf("raw: 0x%p\n", raw); // Outputs 0x00000000
if(raw != NULL)
{ // Only prints when less than 10 characters are entered
free(raw);
printf("raw is not NULL\n");
}
free(buf);
return 0;
}
当我输入少于10个字符时,这可以正常工作,当我输入正好10个字符时,我得到分段错误,当我输入10个以上时,输出显示raw为NULL。应该注意的是,raw的大小是1024 malloc'd字节,所以我应该有更多的工作空间。
解析功能是:
int parse(char *src, char **dst)
{
int num_valid = 0, len = strlen(src), j = 0;
// Count number of valid characters
for(int i = 0; i < len; i++)
{
if(src[i] == 'A')
++num_valid;
}
*dst = malloc(num_valid);
for(int i = 0; i < len; i++)
{
if(src[i] == 'A')
*dst[j++] = src[i];
}
// For debugging:
printf("src: 0x%p\n", src); // outputs correct address
return num_valid;
}
此函数输出正确的地址,并正确分配和填充dst。我在这里略微修改了代码,这基本上是我的代码的一种非常简化的形式。我编译并运行它(gcc test.c -Werror -Wall)具有相同的结果。只有在此函数返回后,我的原始指针变为NULL,否则我会得到段错误。
有人能指出我正确的方向吗?告诉我究竟是我做错了什么?从昨天开始,我一直在调试这段小代码,这让我很生气。
答案 0 :(得分:6)
这并不意味着你的意思:
*dst[j++] = src[i];
你的意思是
(*dst)[j++] = src[i];
你写的是:
*(dst[j++]) = src[i];
dst[1]
是跟随变量buf
发生的任何事情,因此您使用来自随机存储位置的地址并覆盖它可能指向的任何地址;那种未定义的行为。
@ pm100在注释中指出,将缓冲区保存在临时变量中通常是更好的样式:
char* buf = malloc(num_valid);
if (!buf) { /* Handle allocation failure */ }
*dst = buf;
/* ... */
/* In loop */
buf[j++] = src[i];