free()抱怨无效指针

时间:2016-11-18 17:09:10

标签: c string printf concatenation

我正在尝试通过连接一些值来逐个构建一个字符串,以获得类似的东西:

|0x0F64:0x0063:0x1A|0x7CC4:0x0073:0x1A|0x0A51:0xA29A:0x9C|0xD49D:0x0058:0x10|

我想使用动态变量,因为NB_ELEMENT可能会得到改进。

#include <stdio.h>
#include <stdlib.h>

#define NB_ELEMENT 4
typedef struct
{
   unsigned short  u16Val1;
   unsigned short  u16Val2;
   unsigned char   u8Val3;
}stElement;

stElement element[NB_ELEMENT] = {{ 0 }};

int main()
{
    element[0].u16Val1 = 3940;
    element[0].u16Val2 = 99;
    element[0].u8Val3 = 26; 

    element[1].u16Val1 = 31940;
    element[1].u16Val2 = 115;
    element[2].u8Val3 = 26;           

    element[2].u16Val1 = 2641;
    element[2].u16Val2 = 41620;
    element[2].u8Val3 = 156; 

    element[3].u16Val1 = 52429;
    element[3].u16Val2 = 88;
    element[3].u8Val3 = 16;

    char *str = malloc(NB_ELEMENT * sizeof element);

    snprintf(str, sizeof element, "|0x%04x:0x%04x:0x%x\n",element[0].u16Val1,
                                                      element[0].u16Val2,
                                                      element[0].u8Val3);

    str += sprintf(str, "|0x%04x:0x%04x:0x%x\n",element[1].u16Val1,
                                            element[1].u16Val2,
                                            element[1].u8Val3);

    fprintf(stdout, "%s\n", str);
    free(str);
    return 0;
}

上面的代码返回:

*** Error in `./TEST': free(): invalid pointer: 0x0000000000cac023 ***

但是,我设法打印|0x0f64:0x0063:0x1a但是avec添加了str + = sprintf ..,就会发生错误。

4 个答案:

答案 0 :(得分:7)

问题在于:

str += sprintf(str, "|0x%04x:0x%04x:0x%x\n",element[1].u16Val1,
                                        element[1].u16Val2,
                                        element[1].u8Val3);

修改 str中的指针。因此,当您将其移至free之后,它与malloc给您的指针不同,这使free的工作相当困难。

解决方案:不要修改指针。如果要通过添加写入指针的字符数来跟踪缓冲区中的位置,请使用不同的指针:

char *str = malloc(NB_ELEMENT * sizeof element);
// ...
char * p = str;
// ...
p += sprintf(p, "|0x%04x:0x%04x:0x%x\n",element[1].u16Val1,
                                        element[1].u16Val2,
                                        element[1].u8Val3);
// ...
free(str);

答案 1 :(得分:4)

因为您没有传递free() malloc()返回的相同指针。所以,undefined behaviour

这句话:

 str += sprintf(str, "|0x%04x:0x%04x:0x%x\n",element[1].u16Val1,
                                             element[1].u16Val2,
                                             element[1].u8Val3);

您已更改str

来自free()

  

free()函数释放ptr指向的内存空间   先前对malloc(),calloc()或realloc()的调用必须返回。否则,或者如果已经调用了free(ptr)   之前,发生未定义的行为。如果ptr为NULL,则不进行任何操作   进行。

(强调我的)。

答案 2 :(得分:2)

您无法在C中以这种方式连接字符串。

str += something

只是将str中存储的地址更改为其他内容,然后使其成为一个无效的指针(因为它不是从malloc / calloc获得的值)。

如果你想连接字符串,你应该使用DocumentsProvider,最初分配一个足够大的缓冲区以适应整个内容。

答案 3 :(得分:2)

 man 3 free
  

free()函数释放ptr指向的内存空间,必须由之前调用malloc(),calloc()或          realloc()的即可。否则,或者如果之前已经调用了free(ptr),则会发生未定义的行为。

由于str是通过向从malloc()获取的指针添加数字而获得的指针,因此它不符合此要求,并且会产生未定义的行为。

不胜感激它是你系统上的一个严重失败 - 在某些系统上,它会导致内存泄漏或奇怪的内存损坏,只有当你的程序开始产生垃圾时才会显露出来。

您的代码还有其他问题。您应该查看C书中关于指针和字符串的章节。