2

文字列を文字列の配列に変換する関数を作成しました。テストプログラムは、次のものに置き換えるまで正常に動作int main()しますint main(int argc, char** argv)

コンソール:

*** glibc detected *** ./a.out: realloc(): invalid pointer: 0xbfdc6370 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x75ee2)[0xb764eee2]
/lib/i386-linux-gnu/libc.so.6(realloc+0x25d)[0xb765355d]
/lib/i386-linux-gnu/libc.so.6(realloc+0x273)[0xb7653573]
./a.out[0x80485d6]
./a.out[0x80486bf]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb75f24d3]
./a.out[0x8048461]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:05 2889457    /home/tg/a.out
08049000-0804a000 r--p 00000000 08:05 2889457    /home/tg/a.out
0804a000-0804b000 rw-p 00001000 08:05 2889457    /home/tg/a.out
085cc000-085ed000 rw-p 00000000 00:00 0          [heap]
b75a5000-b75c1000 r-xp 00000000 08:05 5637044    /lib/i386-linux-gnu/libgcc_s.so.1
b75c1000-b75c2000 r--p 0001b000 08:05 5637044    /lib/i386-linux-gnu/libgcc_s.so.1
b75c2000-b75c3000 rw-p 0001c000 08:05 5637044    /lib/i386-linux-gnu/libgcc_s.so.1
b75d8000-b75d9000 rw-p 00000000 00:00 0 
b75d9000-b777c000 r-xp 00000000 08:05 5636109    /lib/i386-linux-gnu/libc-2.15.so
b777c000-b777d000 ---p 001a3000 08:05 5636109    /lib/i386-linux-gnu/libc-2.15.so
b777d000-b777f000 r--p 001a3000 08:05 5636109    /lib/i386-linux-gnu/libc-2.15.so
b777f000-b7780000 rw-p 001a5000 08:05 5636109    /lib/i386-linux-gnu/libc-2.15.so
b7780000-b7783000 rw-p 00000000 00:00 0 
b7797000-b779a000 rw-p 00000000 00:00 0 
b779a000-b779b000 r-xp 00000000 00:00 0          [vdso]
b779b000-b77bb000 r-xp 00000000 08:05 5636227    /lib/i386-linux-gnu/ld-2.15.so
b77bb000-b77bc000 r--p 0001f000 08:05 5636227    /lib/i386-linux-gnu/ld-2.15.so
b77bc000-b77bd000 rw-p 00020000 08:05 5636227    /lib/i386-linux-gnu/ld-2.15.so
bfda7000-bfdc8000 rw-p 00000000 00:00 0          [stack]
Aborted (core dumped)

コード:

/* tokenize function*/
int tokenize(char ***tokenList, char *string, char *separators){
    /* initialization */
    int count = 0;                      // token counter
    int length = strlen(string) + 1;    // length of string array
    int lengthSep = strlen(separators); // number of separators
    char *memory = malloc(length);      // copy of string; string token array in the end
    if (memory == NULL)                 // error treatment for malloc
        return -1;
    memcpy(memory, string, length);
    char *lastPos = memory;             // start position of the current string token in memory
    char **tempList;                    // temporary pointer to token array

    /* find occurences of separators and replace them with '\0', reallocate tempList for each new string token built in that way */
    for (int i = 0; i < length; i++){
        /* check if current character is a separator */
        for (int j = 0; j <= lengthSep; j++){
            if (*(memory + i) == separators[j]){
                count++;                            // increase string counter
                *(memory + i) = '\0';               // replace separator by '\0'
                tempList = realloc(tempList, sizeof(char*) * count);    // reallocate tempList
                if (tempList == NULL){              // error treatment for realloc
                    free(memory);
                    free(tempList);
                    return -1;
                }                                   
                tempList[count-1] = lastPos;        // add pointer to the new string to the end of tempList
                lastPos = memory + i + 1;           // calculate starting position for the next string token
                break;                              // escape from inner loop (found matching separator)
            }
        }
    }
    *tokenList = tempList;
    return count;
}
int main(){
    char string[100] = "aa/bbb/cccc";
    char separators[2] = "/";
    char **tokenList;
    int count;
    count = tokenize(&tokenList,string, separators);
    printf("count: %d\n", count);
    printf("item: %s\n", tokenList[0]);
    return EXIT_SUCCESS;

}
4

2 に答える 2

12

初期化しないtempListので、最初に電話をかけるtempList = realloc(tempList,...ときは、任意のアドレスを拡張/解放しようとしています。

最も簡単な修正は、次のように初期化tempListすることです。NULL

char **tempList = NULL;

余談ですが、コード

tempList = realloc(tempList, sizeof(char*) * count);
if (tempList == NULL){
    free(memory);
    free(tempList);
    return -1;
}

別の小さなバグが含まれています。realloc失敗してtempListがである場合はNULL、の以前の値がリークされておりtempList、呼び出しfree(tempList)は何もしません。メモリ不足エラーを適切に処理したい場合は、次のようなことを行う必要があります。

void* tmp = realloc(tempList, sizeof(char*) * count);
if (tmp == NULL){
    free(memory);
    free(tempList);
    return -1;
}
tempList = tmp;
于 2012-12-20T15:16:54.423 に答える
5

templistは初期化されていないため、宣言されているスタックにあるすべてのガベージが含まれています。

次に、それをに渡して、realloc()それが指すメモリのサイズを変更します。しかしrealloc()、それが有効なものを指していないことに気づきます。

于 2012-12-20T15:17:08.093 に答える