用'无效指针'调用free()崩溃

时间:2018-06-04 23:48:06

标签: c free

我正在编写一个程序来解析字典文本文件(确切地说是cedict字典)并将所有行插入到sqlite3数据库中。我创建了一个表示字典条目的结构:

typedef struct {
    char *      traditional;
    char *      simplified;
    char *      pinyin;
    char *      english;
} entry_t;

我正在解析该行并在结构中存储字符串(使用malloc语句创建),并在while循环结束时读取文件中的所有行,释放已分配的内存。这适用于文件中99%以上的行,但是在第1137行,对free的调用失败,代码为134,消息为“invalid pointer”。我的第一个想法是我写了一个内存地址以外的malloc内存区域,但经过双重检查后似乎并非如此。如果我增加malloc字符串的大小来保存该值,则它会在另一行上失败。我也试过在Valgrind中分析它,但不完全确定输出意味着什么,但我确实看到它在116,000行上只失败了3次。不知道这里发生了什么。

while(-1 != getline(line, size, fid)) {
    clear(entry);
    indices[0] = *line;
    for (size_t i = 1; i < sizeof(indices) / sizeof(char *); i++) {
        indices[i] = strchr(indices[i - 1], search [i - 1]);
    }
    entry->traditional = malloc(indices[1] - indices[0] + 1);
    memcpy(entry->traditional, indices[0], indices[1] - indices[0]);
    entry->traditional[indices[1] - indices[0]] = '\0';

    entry->simplified = malloc(indices[2] - indices[1] - 2);
    memcpy(entry->simplified, indices[1] + 1, indices[2] - indices[1] - 2);
    entry->simplified[indices[2] - indices[1] - 2] = '\0';

    entry->pinyin = malloc(indices[3] - indices[2] - 1);
    memcpy(entry->pinyin, indices[2] + 1, indices[3] - indices[2] - 1);
    entry->pinyin[indices[3] - indices[2] - 1] = '\0';

    entry->english = malloc(strlen(indices[4]) - 1);
    memcpy(entry->english, indices[4], strlen(indices[4]) - 2);
    entry->english[strlen(indices[4]) - 2] = '\0';

    sqlite3_bind_int64(stmt, 1, ++id);
    sqlite3_bind_text(stmt, 2, entry->traditional, -1, NULL);
    sqlite3_bind_text(stmt, 3, entry->simplified, -1, NULL);
    sqlite3_bind_text(stmt, 4, entry->pinyin, -1, NULL);
    sqlite3_bind_text(stmt, 5, entry->english, -1, NULL);

    while (SQLITE_DONE != sqlite3_step(stmt));
    sqlite3_reset(stmt);

    free(entry->traditional);
    free(entry->simplified);
    free(entry->pinyin);
    free(entry->english);     // <---- this is where it crashes
    printf("inserted: %lld items\n", id);
}

在此代码中,clear是memset的一个宏(entry,0,sizeof(* entry)),而indices数组包含指向有助于解析的特定位置的指针。此外,对我的代码的任何其他建设性批评将不胜感激。

编辑:Valgrind输出。目前正在等待程序在Valgrind完成运行(总共30分钟),但我注意到由于之前的printfs我在顶部有一些输出。它低于

==5629== Invalid write of size 1
==5629==    at 0x1090AD: main (main.c:74)
==5629==  Address 0x5d28291 is 0 bytes after a block of size 1 alloc'd
==5629==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5629==    by 0x10904E: main (main.c:72)
==5629== 
==5629== Invalid write of size 1
==5629==    at 0x10912B: main (main.c:78)
==5629==  Address 0x5d282e3 is 0 bytes after a block of size 3 alloc'd
==5629==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5629==    by 0x1090CC: main (main.c:76)
==5629== 
==5629== Invalid read of size 1
==5629==    at 0x4C32D04: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5629==    by 0x4E792DA: ??? (in /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6)
==5629==    by 0x4E89148: ??? (in /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6)
==5629==    by 0x1091FF: main (main.c:86)
==5629==  Address 0x5d28291 is 0 bytes after a block of size 1 alloc'd
==5629==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5629==    by 0x10904E: main (main.c:72)
==5629== 
==5629== Invalid read of size 1
==5629==    at 0x4C32D04: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5629==    by 0x4E792DA: ??? (in /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6)
==5629==    by 0x4E89148: ??? (in /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6)
==5629==    by 0x109226: main (main.c:87)
==5629==  Address 0x5d282e3 is 0 bytes after a block of size 3 alloc'd
==5629==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5629==    by 0x1090CC: main (main.c:76)

0 个答案:

没有答案