晚上被这个内存扩展崩溃的问题折腾的有点崩溃, 当答案揭晓的那一刻, 恍然大悟, 原来如此简单.
练习题目: 输入一个字符串, 根据字母进行排序, 说白了就是一个简单的冒泡
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdbool.h>
- #include <string.h>
- #define BUF_LEN 100
- #define COUNT 5
- int main(void)
- {
- char buf[BUF_LEN];
- size_t str_count = 0;
- size_t capacity = COUNT;
- char **pS = calloc(capacity, sizeof(char*));
- char **psTemp = NULL;
- char *pTemp = NULL;
- size_t str_len = 0;
- bool sorted = false;
- printf("Enter strings to be sorted, one per line. Press Enter to end:\n");
- char *ptr = NULL;
- while(true)
- {
- ptr = fgets(buf, BUF_LEN, stdin);
- if(!ptr)
- {
- printf("Error reading string.\n");
- free(pS);
- pS = NULL;
- return 1;
- }
- if(*ptr == '\n')
- break;
- if(str_count == capacity)
- {
- capacity += capacity/4;
- if(!(psTemp = realloc(pS, capacity)))
- return 1;
- pS = psTemp;
- }
- str_len = strlen(buf) + 1;
- if(!(pS[str_count] = malloc(str_len)))
- return 2;
- strcpy(pS[str_count++], buf);
- }
- while(!sorted)
- {
- sorted = true;
- size_t i = 0;
- for(; i <str_count - 1; i++)
- {
- if(strcmp(pS[i], pS[i+1])> 0)
- {
- sorted = false;
- pTemp = pS[i];
- pS[i] = pS[i+1];
- pS[i + 1] = pTemp;
- }
- }
- }
- printf("Your input sorted in ascending sequence is:\n\n");
- size_t i = 0;
- for(; i < str_count; i++)
- {
- printf("%s", pS[i]);
- free(pS[i]);
- pS[i] = NULL;
- }
- free(pS);
- pS = NULL;
- return 0;
- }
上面标黄处, 首先是通过 calloc 进行内存分配, 初始是 capacity 的长度是 5, 接着判断当输入的字符串个数等于 5 了, 那么就动态的扩展内存, 继续按 25% 的速度增长. 就是在扩展这里, 一直报错:
- *** Error in `./program714.out': realloc(): invalid next size: 0x0000000002365010 ***
- ======= Backtrace: =========
- /lib64/libc.so.6(+0x7f5d4)[0x7f476bff35d4]
- /lib64/libc.so.6(+0x83bd8)[0x7f476bff7bd8]
- /lib64/libc.so.6(realloc+0x1d2)[0x7f476bff9832]
- ./program714.out[0x4008ea]
- /lib64/libc.so.6(__libc_start_main+0xf5)[0x7f476bf963d5]
- ./program714.out[0x400729]
- ======= Memory map: ========
- 00400000-00401000 r-xp 00000000 fd:01 1321539 /home/wlf/practice/program714.out
- 00600000-00601000 r--p 00000000 fd:01 1321539 /home/wlf/practice/program714.out
- 00601000-00602000 rw-p 00001000 fd:01 1321539 /home/wlf/practice/program714.out
- 02365000-02386000 rw-p 00000000 00:00 0 [heap]
- 7f4764000000-7f4764021000 rw-p 00000000 00:00 0
- 7f4764021000-7f4768000000 ---p 00000000 00:00 0
- 7f476bd5e000-7f476bd73000 r-xp 00000000 fd:01 655380 /usr/lib64/libgcc_s-4.8.5-20150702.so.1
- 7f476bd73000-7f476bf72000 ---p 00015000 fd:01 655380 /usr/lib64/libgcc_s-4.8.5-20150702.so.1
- 7f476bf72000-7f476bf73000 r--p 00014000 fd:01 655380 /usr/lib64/libgcc_s-4.8.5-20150702.so.1
- 7f476bf73000-7f476bf74000 rw-p 00015000 fd:01 655380 /usr/lib64/libgcc_s-4.8.5-20150702.so.1
- 7f476bf74000-7f476c136000 r-xp 00000000 fd:01 658657 /usr/lib64/libc-2.17.so
- 7f476c136000-7f476c336000 ---p 001c2000 fd:01 658657 /usr/lib64/libc-2.17.so
- 7f476c336000-7f476c33a000 r--p 001c2000 fd:01 658657 /usr/lib64/libc-2.17.so
- 7f476c33a000-7f476c33c000 rw-p 001c6000 fd:01 658657 /usr/lib64/libc-2.17.so
- 7f476c33c000-7f476c341000 rw-p 00000000 00:00 0
- 7f476c341000-7f476c363000 r-xp 00000000 fd:01 658372 /usr/lib64/ld-2.17.so
- 7f476c557000-7f476c55a000 rw-p 00000000 00:00 0
- 7f476c55e000-7f476c562000 rw-p 00000000 00:00 0
- 7f476c562000-7f476c563000 r--p 00021000 fd:01 658372 /usr/lib64/ld-2.17.so
- 7f476c563000-7f476c564000 rw-p 00022000 fd:01 658372 /usr/lib64/ld-2.17.so
- 7f476c564000-7f476c565000 rw-p 00000000 00:00 0
- 7ffde3137000-7ffde3158000 rw-p 00000000 00:00 0 [stack]
- 7ffde31c5000-7ffde31c7000 r-xp 00000000 00:00 0 [vdso]
- ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
- Aborted
代码看来看去发现没毛病, 唯一能怀疑的地方就是内存扩展的那一行, 经过几番折腾, 发现只要一到需要增长调用 realloc 就报错, 最后回去看 calloc, 只能一拍大腿骂娘了, 字节计算的类型不对啊, 一个是按 char*(相当于二维数组 pS[][]中的子数组 pS[])来计算字节, 一个是按字符 (char) 来计算字节, 得到的内存大小必然不同啊. 把 realloc 的第二个参数加上这个就解决了:
if(!(psTemp = realloc(pS, capacity*sizeof(char*))))
编码需谨慎, 差之毫厘, 谬之千里, 一点小小的 bug 都能让程序崩溃.
来源: http://www.bubuko.com/infodetail-3007018.html