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

Jac*_*b H 0 c malloc pointers segmentation-fault

我使用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;
}
Run Code Online (Sandbox Code Playgroud)

当我输入少于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;
}
Run Code Online (Sandbox Code Playgroud)

此函数输出正确的地址,并正确分配和填充dst.我在这里略微修改了代码,这基本上是我的代码的一种非常简化的形式.我编译并运行它(gcc test.c -Werror -Wall)具有相同的结果.只有在此函数返回后,我的原始指针变为NULL,否则我会得到段错误.

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

ric*_*ici 6

这并不意味着你认为它意味着什么:

*dst[j++] = src[i];
Run Code Online (Sandbox Code Playgroud)

你的意思是

(*dst)[j++] = src[i];
Run Code Online (Sandbox Code Playgroud)

你写的是什么意思:

*(dst[j++]) = src[i];
Run Code Online (Sandbox Code Playgroud)

dst[1]无论发生什么事情都跟随变量buf,所以你正在使用随机存储器位置的地址并覆盖它可能指向的任何地址; 这是未定义的行为.

正如@ pm100在注释中指出的那样,将缓冲区保存在临时变量中通常是更好的样式:

char* buf = malloc(num_valid);
if (!buf) { /* Handle allocation failure */ }
*dst = buf;
/* ... */
  /* In loop */
  buf[j++] = src[i];
Run Code Online (Sandbox Code Playgroud)