代码改变世界

C 编程异常 — double free or corruption (fasttop)

2020-04-09 23:08  云物互联  阅读(2370)  评论(0编辑  收藏  举报

问题:运行代码的时候程序崩溃。

*** Error in `./parsing': double free or corruption (fasttop): 0x00000000023d2350 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x81679)[0x7f349ead0679]
./parsing[0x4011fe]
./parsing[0x401b07]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7f349ea71505]
./parsing[0x400f59]
======= Memory map: ========
00400000-00413000 r-xp 00000000 08:01 34603142                           /root/Lispy/parsing
00612000-00613000 r--p 00012000 08:01 34603142                           /root/Lispy/parsing
00613000-00614000 rw-p 00013000 08:01 34603142                           /root/Lispy/parsing
023a4000-023df000 rw-p 00000000 00:00 0                                  [heap]
7f3494000000-7f3494021000 rw-p 00000000 00:00 0
7f3494021000-7f3498000000 ---p 00000000 00:00 0
7f34980e5000-7f34980fa000 r-xp 00000000 08:01 2709898                    /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f34980fa000-7f34982f9000 ---p 00015000 08:01 2709898                    /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f34982f9000-7f34982fa000 r--p 00014000 08:01 2709898                    /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f34982fa000-7f34982fb000 rw-p 00015000 08:01 2709898                    /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f34982fb000-7f349e825000 r--p 00000000 08:01 2129632                    /usr/lib/locale/locale-archive
7f349e825000-7f349e84a000 r-xp 00000000 08:01 2137260                    /usr/lib64/libtinfo.so.5.9
7f349e84a000-7f349ea4a000 ---p 00025000 08:01 2137260                    /usr/lib64/libtinfo.so.5.9
7f349ea4a000-7f349ea4e000 r--p 00025000 08:01 2137260                    /usr/lib64/libtinfo.so.5.9
7f349ea4e000-7f349ea4f000 rw-p 00029000 08:01 2137260                    /usr/lib64/libtinfo.so.5.9
7f349ea4f000-7f349ec12000 r-xp 00000000 08:01 2129638                    /usr/lib64/libc-2.17.so
7f349ec12000-7f349ee12000 ---p 001c3000 08:01 2129638                    /usr/lib64/libc-2.17.so
7f349ee12000-7f349ee16000 r--p 001c3000 08:01 2129638                    /usr/lib64/libc-2.17.so
7f349ee16000-7f349ee18000 rw-p 001c7000 08:01 2129638                    /usr/lib64/libc-2.17.so
7f349ee18000-7f349ee1d000 rw-p 00000000 00:00 0
7f349ee1d000-7f349ef1e000 r-xp 00000000 08:01 2129646                    /usr/lib64/libm-2.17.so
7f349ef1e000-7f349f11d000 ---p 00101000 08:01 2129646                    /usr/lib64/libm-2.17.so
7f349f11d000-7f349f11e000 r--p 00100000 08:01 2129646                    /usr/lib64/libm-2.17.so
7f349f11e000-7f349f11f000 rw-p 00101000 08:01 2129646                    /usr/lib64/libm-2.17.so
7f349f11f000-7f349f15b000 r-xp 00000000 08:01 2137399                    /usr/lib64/libreadline.so.6.2
7f349f15b000-7f349f35b000 ---p 0003c000 08:01 2137399                    /usr/lib64/libreadline.so.6.2
7f349f35b000-7f349f35d000 r--p 0003c000 08:01 2137399                    /usr/lib64/libreadline.so.6.2
7f349f35d000-7f349f363000 rw-p 0003e000 08:01 2137399                    /usr/lib64/libreadline.so.6.2
7f349f363000-7f349f365000 rw-p 00000000 00:00 0
7f349f365000-7f349f387000 r-xp 00000000 08:01 2136893                    /usr/lib64/ld-2.17.so
7f349f574000-7f349f57b000 r--s 00000000 08:01 2137112                    /usr/lib64/gconv/gconv-modules.cache
7f349f57b000-7f349f57f000 rw-p 00000000 00:00 0
7f349f583000-7f349f586000 rw-p 00000000 00:00 0
7f349f586000-7f349f587000 r--p 00021000 08:01 2136893                    /usr/lib64/ld-2.17.so
7f349f587000-7f349f588000 rw-p 00022000 08:01 2136893                    /usr/lib64/ld-2.17.so
7f349f588000-7f349f589000 rw-p 00000000 00:00 0
7ffed1ac3000-7ffed1ae4000 rw-p 00000000 00:00 0                          [stack]
7ffed1af3000-7ffed1af5000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
已放弃

分析

typedef struct lval {
    int type;
    long num;

    /* Count and Pointer to a list of "lval*" */
    struct lval** cell;
    int count;

    /* Error and Symbol types have some string data */
    char *err;
    char *sym;
} lval;

lval *lval_sym(char *sym) {
    lval *v = malloc(sizeof(lval));
    v->type = LVAL_SYM;
    v->sym = malloc(strlen(sym) + 1);
    strcpy(v->sym, sym);
    return v;
}


void lval_del(lval *v) {
    switch (v->type) {
        /* Do nothing special for number type */
        case LVAL_NUM:
            break;

        /* For Err or Sym free the string data */
        case LVAL_ERR:
            free(v->err);
            break;
        case LVAL_SYM:
            free(v->sym);
            break;

        /* If Sexpr then delete all elements inside */
        case LVAL_SEXPR:
            for (int i = 0; i < v->count; i++) {
                lval_del(v->cell[i]);
            }
            /* Also free the memory allocated to contain the pointers */
            free(v->cell);
            break;
    }
    /* Free the memory allocated for the "lval" struct itself */
    free(v);
}

因为上述代码中,结构体变量 lval *lval_sym 中的成员 sym 没有被释放 free(v->sym);,就直接释放了变量自身 free(v)。之所以不进入 switch 条件判断,是因为 v->type 成员的值出现了 Bug。

所以本质的原因还是因为结构体的成员空间还没有被释放就直接释放了结构体变量本身导致的

解决:在释放结构体变量自身的内存空间之前,需要首先将结构体成员指向的内存空间释放掉。