2017-05-15 51 views
-1

以下の関数tokenizeは、sprtがstrの中に存在しない場合、* sizeを0に設定するためのものです。そしてSTRは、「D AO D」は、チャンクは、[1]にNULLポインタをポイントするようになっているし、Nを0に設定する次のコード内の機能をテストする際未定義の動作strtok

void 
tokenize(char *str, 
     const char *sprt /*separator*/, 
     char **buffer, 
     int *size /*tokens length*/) 
{ 
    char *chunk[2] = {NULL, NULL}; 

    //store str value into chunk[0] 
    chunk[0] = calloc(strlen(str)+1, sizeof(char)); 
    strcpy(chunk[0], str); 

    if (buffer!=NULL) 
    { 
    int sz = 0; 
    chunk[1] = strtok(str, sprt); 
    while (chunk[1]!=NULL) 
    { 
     buffer[sz] = calloc(strlen(chunk[1])+1, sizeof(char)); 
     strcpy(buffer[sz], chunk[1]); 
     chunk[1] = strtok(NULL, sprt); 
     sz++; 
    } 
    } 
    else 
    { 
    *size=0; 

    //if chunk is not NULL, the iteration begins => size > 0 
    chunk[1] = strtok(str, sprt); 

    while (chunk[1]!=NULL) 
    { 
     (*size)++; 
     chunk[1] = strtok(NULL, sprt); 
    } 

    printf("size=%i\n", *size); 
    } 

    //restore str value from chunk[0] 
    strcpy(str, chunk[0]); 

    if (chunk[0]!=NULL) free(chunk[0]); 
    if (chunk[1]!=NULL) free(chunk[1]); 
} 

しかしながら、bug: n really needs to be 0!が表示されます、つまり、strtokが期待どおりに動作しなかったことを意味します。

int main() 
{ 
    char *test = calloc(7, sizeof(char)); 
    strcpy(test, "D AO D"); 

    int n; 
    tokenize(test, "|", NULL, &n); 
    if (n>0) 
    printf("bug: n really needs to be 0!\n"); 
    else 
    printf("no bug\n"); 
} 

このUBの原因はわかりません。私は間違っているの?

chunk[1] = strtok(str, sprt); 

そしてwhileループ条件が通過chunk[1]が非NULLポインタであるため、この文字列には"|"区切りがないので

+1

'free(chunk [1])'を呼び出さないでください。 'malloc'ファミリで割り当てたものだけを'フリーズ 'する必要があります –

+0

これはあなたが実行している問題とは関係ありませんが、 'strdup()'が 'malloc () '/' strcpy() 'の組み合わせです。エラーが発生しにくく、読みやすくなります。 –

答えて

2

最初strtok呼び出しは、元の文字列"D AO D"へのポインタを戻します。

および*sizeは、最初の繰り返しで増分されます。次のstrtokコールは、'\0'バイトが終了するとNULLを返し、満たされていない状態でループが終了します。したがって、*size1に等しくなり、これは予想される動作です。

+0

私は、strtokが間違った区切り文字の場合に元の文字列を返すことをリリースしませんでした。ありがとう。 – Kais

+1

@Kais:文字列に区切り文字がない場合、文字列は唯一のトークンです。 –

関連する問題