自由功能失败

时间:2016-09-13 01:31:52

标签: c malloc free

我正在Linux中编写一个简单的程序。其目的是显示GNU版本号。但似乎free()函数对我尖叫。当我执行程序时。它显示以下内容:

*`./a.out':munmap_chunk()出错:指针无效:0x00007fa89f028d8a *

和Backtrace和记忆图。

以下是我的代码:

# include <stdio.h>
# include <gnu/libc-version.h>
# include <string.h>
# include <stdlib.h>

int main(void){
        const char *s;
        s = (const char *)malloc(16*sizeof(char));
        s = gnu_get_libc_version();
        printf("%s\n",s);
        free((char *)s);
        return 0;
}

4 个答案:

答案 0 :(得分:2)

当您使用返回值malloc重新初始化s时,您已丢失gnu_get_libc_version返回的指针。您现在正在尝试free gnu_get_libc_version返回的指针malloc尚未由malloc分配。

在致电gnu_get_libc_version之前,您不需要free,并且在致电后不需要{{1}}。

答案 1 :(得分:1)

s = gnu_get_libc_version();

这不符合你的想象。看起来你希望它填充你先前分配的内存,s所指向的内存。

实际所做的是导致s指向完全不同的地方,某处由函数gnu_get_libc_version决定。

鉴于free错误以及documentation中的示例用法,这个内存从堆中分配而不是的可能性要大于偶数,因此尝试免费它会导致不明确的行为。

假设gnu_get_libc_version实际上确实返回了C风格字符串的地址而且它不是来自堆(并且这似乎是基于上面链接的情况),您不需要分配它的记忆。相反,你可以拥有:

int main(void) {
    const char *s = gnu_get_libc_version();
    printf("%s\n", s);
    return 0;
}

甚至更短(直接使用puts和返回值):

int main(void) {
    puts(gnu_get_libc_version());
    return 0;
}

如果你想要将版本信息放到你自己分配的缓冲区中(假设你有足够的内存),你可以使用:

int main(void){
    const char *s = malloc(16);
    strcpy(s, gnu_get_libc_version());
    printf("%s\n", s); // or puts(s)
    free(s);
    return 0;
}

字符串(从gnu_get_libc_version返回的区域)复制到您自己的缓冲区中,而不是将s更改为指向其他位置。

请注意,我在原始代码中更改了其他一些内容。第一种是删除malloc返回值的显式强制转换。这是不应该在C中完成的事情,因为它可以隐藏某些微妙的错误。 C完全能够隐式地void *返回值转换为另一种指针类型。

第二个是free中的演员表,由于同样的原因,这也是不必要的。

第三个也是最后一个改变是将乘法移除sizeof(char)。标准保证此值为1,因此没有技术原因需要它。

答案 2 :(得分:0)

此函数gnu_get_libc_version()可能返回指向静态内存的指针。

答案 3 :(得分:0)

在这一行

s = gnu_get_libc_version();

您将s重新分配给char *返回的其他gnu_get_libc_version。由s分配的malloc的前一个值丢失,导致内存泄漏。 char *的{​​{1}}返回未由gnu_get_libc_version分配,因此当您在malloc未返回的指针上调用free时,会发生一些错误。 s = gnu_get_libc_version();