malloc'd指针将自身重置为NULL?

时间:2016-10-14 15:47:50

标签: c pointers segmentation-fault malloc

我使用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,否则我会得到段错误。

有人能指出我正确的方向吗?告诉我究竟是我做错了什么?从昨天开始,我一直在调试这段小代码,这让我很生气。

1 个答案:

答案 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];