user-0 提问: C语言错误 : free(): invalid next size (fast): 0x0000000000c34030 

回复:
user: user-0
content: 引用 5 楼 张博约 的回复:1.   指针数组 'ret' 越界了； 2.   calloc分配的内存的大小等于两个参数之积， 第二个参数为0时该接口的行为不明确，具体取决于库的实现； 3.  【建议】 如果要以‘|’为分界符拆分字符串，可以看看strtok 接口。 根据大佬所说，特意去看了下calloc函数的功能，以前的错误理解函数功能以及参数，正确的定义应该为：void *calloc(size_t nmemb, size_t size); 现做修改如下： 1、将上面程序中所有calloc函数的第二参数修改为“sizeof(char *)或者sizeof(char **)”； 2、将上面程序中 ret = (char **)calloc(sizeof(char **), 0); 修改成  ret = (char **)calloc(sizeof(char **) * strLen, sizeof(char **)); 这样即可正常运行了。

user: user-0
content: 引用 3 楼 真相重于对错 的回复:而且你的代码有内存泄露 因为ret是二级指针，所以他相当于一个指针数组，其中每个元素都是指针，要释放ret之前，还要释放它所包含每个指针。 按照大佬的说明修改代码，增加了二级指针的内存大小，增加了malloc与free的匹配的程序，现在修改成了下面这样： #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h>  int main(int argc, const char **argv) {     char *srcStr = "1111|22222|100.215|false|00000000|000.003|00100|00122|00133";     char *srcTmp = srcStr;      char idx = '|';       int strLen = strlen(srcStr);     char *tmp = (char *)calloc(sizeof(char) * (strLen + 1), 0);     char **ret = NULL;      ret = (char **)calloc(sizeof(char **) * 10, 0);      printf("line = %d, ret    = %p, malloc = %ld\n", __LINE__, ret, sizeof(char **));      int i = 0;     while ((tmp = strchr(srcTmp, idx)) != NULL)     {          ret[i] = malloc(sizeof(char) * (strLen + 1));         memset(ret[i], 0, sizeof(char) * (strLen + 1));         strncpy(ret[i], srcTmp, strlen(srcTmp) - strlen(tmp));         printf("line = %d, ret[%d] = %p, malloc = %ld, %s, %ld, %ld\n",             __LINE__, i, ret[i], sizeof(char) * (strLen + 1), ret[i],             strlen(srcTmp), strlen(tmp));         srcTmp = tmp + 1;         i++;     }     ret[i] = malloc(sizeof(char) * (strLen + 1));     memset(ret[i], 0, sizeof(char) * (strLen + 1));     strncpy(ret[i], srcTmp, strlen(srcTmp));     printf("line = %d, ret[%d] = %p, malloc = %ld, %s\n", __LINE__,          i, ret[i], sizeof(char) * (strLen + 1), ret[i]);      for(int j = 0; j < i; j++)     {         free(ret[j]);         printf("Line = %d, free(ret[%d] = %p\n", __LINE__, j, ret[j] );         ret[j] = NULL;     }     free(tmp);     free(ret);      return 0; }  运行的结果为： $ ./a.out   line = 17, ret    = 0x1c4b030, malloc = 8 line = 26, ret[0] = 0x1c4b460, malloc = 60, 1111, 59, 55 line = 26, ret[1] = 0x1c4b4b0, malloc = 60, 22222, 54, 49 line = 26, ret[2] = 0x1c4b500, malloc = 60, 100.215, 48, 41 line = 26, ret[3] = 0x1c4b550, malloc = 60, false, 40, 35 line = 26, ret[4] = 0x1c4b5a0, malloc = 60, 00000000, 34, 26 line = 26, ret[5] = 0x1c4b5f0, malloc = 60, 000.003, 25, 18 line = 26, ret[6] = 0x1c4b640, malloc = 60, 00100, 17, 12 line = 26, ret[7] = 0x1c4b690, malloc = 60, 00122, 11, 6 line = 34, ret[8] = 0x1c4b6e0, malloc = 60, 00133 Line = 40, free(ret[0] = 0x1c4b460 Line = 40, free(ret[1] = 0x1c4b4b0 Line = 40, free(ret[2] = 0x1c4b500 Line = 40, free(ret[3] = 0x1c4b550 段错误 (核心已转储)

user: user-1
content: 1.   指针数组 'ret' 越界了； 2.   calloc分配的内存的大小等于两个参数之积， 第二个参数为0时该接口的行为不明确，具体取决于库的实现； 3.  【建议】 如果要以‘|’为分界符拆分字符串，可以看看strtok 接口。

user: user-2
content: 引用 楼主 smartergirl 的回复:本人小白首先向各位大佬们致敬！祝大佬们哪哪都好！ 本人小白在学习C语言指针的时候遇到了一个比较难的问题，目前已经处于无处下爪的阶段，特来向各位大佬请教！ 下面是本人编写的代码，在运行过程中会出现如题错误。 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h>  int main(int argc, const char **argv) {     char *srcStr = "1111|22222|100.215|false|00000000|000.003|00100|00122|00133";     char *srcTmp = srcStr;     char idx = '|';       int strLen = strlen(srcStr);     char *tmp = (char *)calloc(sizeof(char) * (strLen + 1), 0);     char **ret = NULL;      ret = (char **)calloc(sizeof(char **), 0);      printf("line = %d, ret = %p, malloc = %ld\n", __LINE__, ret, sizeof(char **));      int i = 0;     while ((tmp = strchr(srcTmp, idx)) != NULL)     {          ret[i] = malloc(sizeof(char) * (strLen + 1));         memset(ret[i], 0, sizeof(char) * (strLen + 1));         strncpy(ret[i], srcTmp, strlen(srcTmp) - strlen(tmp));         printf("line = %d, ret[%d] = %p, malloc = %ld, %s, %ld, %ld\n",             __LINE__, i, ret[i], sizeof(char) * (strLen + 1), ret[i],             strlen(srcTmp), strlen(tmp));         srcTmp = tmp + 1;         i++;     }     ret[i] = malloc(sizeof(char) * (strLen + 1));     memset(ret[i], 0, sizeof(char) * (strLen + 1));     strncpy(ret[i], srcTmp, strlen(srcTmp));     printf("line = %d, ret[%d] = %p, malloc = %ld, %s\n", __LINE__,          i, ret[i], sizeof(char) * (strLen + 1), ret[i]);     free(tmp);     free(ret);      return 0; } 使用系统为Ubuntu 16.04 LTS，编译为 gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.10) 下面是错误的提示信息： $ ./a.out  line = 20, ret = 0x1881030, malloc = 8 line = 29, ret[0] = 0x1881460, malloc = 58, 1111, 57, 53 line = 29, ret[1] = 0x18814b0, malloc = 58, 22222, 52, 47 line = 29, ret[2] = 0x1881500, malloc = 58, 100215, 46, 40 line = 29, ret[3] = 0x1881550, malloc = 58, false, 39, 34 line = 29, ret[4] = 0x18815a0, malloc = 58, 00000000, 33, 25 line = 29, ret[5] = 0x18815f0, malloc = 58, 000003, 24, 18 line = 29, ret[6] = 0x1881640, malloc = 58, 00100, 17, 12 line = 29, ret[7] = 0x1881690, malloc = 58, 00122, 11, 6 line = 37, ret[8] = 0x18816e0, malloc = 58, 00133 *** Error in `./a.out': free(): invalid next size (fast): 0x0000000001881030 *** ======= Backtrace: ========= /lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f0ce19667e5] /lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7f0ce196f37a] /lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7f0ce197353c] ./a.out[0x400a01] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f0ce190f830] ./a.out[0x400659] ======= Memory map: ======== 00400000-00401000 r-xp 00000000 08:07 664382                             /home/songtb/Desktop/debug/a.out 00600000-00601000 r--p 00000000 08:07 664382                             /home/songtb/Desktop/debug/a.out 00601000-00602000 rw-p 00001000 08:07 664382                             /home/songtb/Desktop/debug/a.out 01881000-018a2000 rw-p 00000000 00:00 0                                  [heap] 7f0cdc000000-7f0cdc021000 rw-p 00000000 00:00 0  7f0cdc021000-7f0ce0000000 ---p 00000000 00:00 0  7f0ce16d9000-7f0ce16ef000 r-xp 00000000 08:01 396993                     /lib/x86_64-linux-gnu/libgcc_s.so.1 7f0ce16ef000-7f0ce18ee000 ---p 00016000 08:01 396993                     /lib/x86_64-linux-gnu/libgcc_s.so.1 7f0ce18ee000-7f0ce18ef000 rw-p 00015000 08:01 396993                     /lib/x86_64-linux-gnu/libgcc_s.so.1 7f0ce18ef000-7f0ce1aaf000 r-xp 00000000 08:01 396955                     /lib/x86_64-linux-gnu/libc-2.23.so 7f0ce1aaf000-7f0ce1caf000 ---p 001c0000 08:01 396955                     /lib/x86_64-linux-gnu/libc-2.23.so 7f0ce1caf000-7f0ce1cb3000 r--p 001c0000 08:01 396955                     /lib/x86_64-linux-gnu/libc-2.23.so 7f0ce1cb3000-7f0ce1cb5000 rw-p 001c4000 08:01 396955                     /lib/x86_64-linux-gnu/libc-2.23.so 7f0ce1cb5000-7f0ce1cb9000 rw-p 00000000 00:00 0  7f0ce1cb9000-7f0ce1cdf000 r-xp 00000000 08:01 396927                     /lib/x86_64-linux-gnu/ld-2.23.so 7f0ce1ebc000-7f0ce1ebf000 rw-p 00000000 00:00 0  7f0ce1edd000-7f0ce1ede000 rw-p 00000000 00:00 0  7f0ce1ede000-7f0ce1edf000 r--p 00025000 08:01 396927                     /lib/x86_64-linux-gnu/ld-2.23.so 7f0ce1edf000-7f0ce1ee0000 rw-p 00026000 08:01 396927                     /lib/x86_64-linux-gnu/ld-2.23.so 7f0ce1ee0000-7f0ce1ee1000 rw-p 00000000 00:00 0  7ffe87400000-7ffe87421000 rw-p 00000000 00:00 0                          [stack] 7ffe8751c000-7ffe8751f000 r--p 00000000 00:00 0                          [vvar] 7ffe8751f000-7ffe87521000 r-xp 00000000 00:00 0                          [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall] 已放弃 (核心已转储)   小白，积分不多，已经全部上缴了。。。。。  malloc和free成对使用  只看到ret[i] = malloc(sizeof(char) * (strLen + 1)); 没有看到free(ret[i])呀

user: user-3
content: 而且你的代码有内存泄露 因为ret是二级指针，所以他相当于一个指针数组，其中每个元素都是指针，要释放ret之前，还要释放它所包含每个指针。

user: user-3
content: 你这个肯定不对 ret 是一个二级指针，你只alloc了一个元素，然后你又用ret[i]方式写入了好多元素，所以free的时候要出错

user: user-0
content: 顺便说一下，在有一些情况下是可以正常运行的。比如这样的情况下： 1、将上面的代码中第10行中` char idx = '|';   ` 修改成  ` char idx = '.';   `，那么就可以正常运行，运行结果为： $ ./a.out  line = 17, ret = 0x1676030, malloc = 8 line = 26, ret[0] = 0x1676460, malloc = 60, 1111|22222|100, 59, 45 line = 26, ret[1] = 0x16764b0, malloc = 60, 215|false|00000000|000, 44, 22 line = 34, ret[2] = 0x1676500, malloc = 60, 003|00100|00122|00133