【问题标题】:free() complains about invalid pointerfree() 抱怨指针无效
【发布时间】:2017-04-02 15:03:07
【问题描述】:

我试图通过连接一些值在我的程序中逐个构建一个字符串,以获得类似的东西:

|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..,出现了错误。

【问题讨论】:

  • 伙计,在 C 语言中,str += 不是串联,而是递增一个指针。 C 中字符串的连接需要两个缓冲区(from 和 to)和函数 strcat
  • 其他问题:在char *str = malloc(NB_ELEMENT * sizeof element); 中,告诉我NB_ELEMENT * sizeof element 与您正在创建的字符串的大小有何关系?
  • 应该使用类似size = ...; char *str = malloc(size); int n = snprintf(str, size, ...); if (n &lt; 0 || n &gt;= size) Error();

标签: c string printf concatenation


【解决方案1】:

问题出在这里:

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);

【讨论】:

    【解决方案2】:

    因为您没有传递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,则不进行任何操作 执行。

    (强调我的)。

    【讨论】:

      【解决方案3】:

      您不能在 C 中以这种方式连接字符串。

      str += something
      

      只需将存储在str 中的地址更改为其他地址,然后使其成为要释放的无效指针(因为它不再是从malloc/calloc 获得的值)。

      如果你想连接字符串,你应该使用strncat,首先分配一个足够大的缓冲区来容纳整个内容。

      【讨论】:

      • 他没有连接,因为sprintf() 不返回字符串。它返回打印的字符数,因此str 现在指向缓冲区中要打印的下一个位置。
      【解决方案4】:
       man 3 free
      

      free() 函数释放 ptr 指向的内存空间,这一定是之前调用 malloc()、calloc() 或 重新定位()。否则,或者如果之前已经调用过 free(ptr),则会发生未定义的行为。

      由于你的str是从malloc()得到的指针加上一个数字得到的指针,所以不符合这个要求,导致未定义的行为。

      感谢这是您系统上的严重故障 - 在某些系统上,它会导致内存泄漏或奇怪的内存损坏,只有在您的程序开始产生垃圾时才会显示出来。

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

      【讨论】:

        猜你喜欢
        • 2012-02-21
        • 1970-01-01
        • 2013-06-27
        • 2015-03-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-07
        • 1970-01-01
        相关资源
        最近更新 更多