2016-07-12 3 views
1

文字列をトークン化しようとしています。アドレスが範囲外で、mallocによるメモリリーク

入力配列(文字**)に格納されている異なる行がある

異なるアレイに生成され、異なるトークンを格納するために、次の関数を使用しています。

int tokenize_string(int max_lines,char *input_lines[max_lines],char **tokens) 
{ 
    char *token; 
    int index,token_index=0; 

    for(index = 0; index < max_lines;++index) 
    { 
     token = strtok(input_lines[index]," "); 

     while(token != NULL) 
     { 
      tokens[token_index] = malloc(sizeof(char*)); 
      tokens[token_index] = token; 
      token = strtok(NULL," "); 
      token_index++; 
     } 
    } 
    return token_index; 
} 

を使用valgrindの以下のときには、私は問題がmallocforループであることを知っている

==25710== Invalid write of size 8 
==25710== at 0x400AA6: tokenize_string (functions.c:28) 
==25710== by 0x400953: main (main.c:29) 
==25710== Address 0x51c3048 is 0 bytes after a block of size 8 alloc'd 
==25710== at 0x4C27A2E: malloc (vg_replace_malloc.c:270) 
==25710== by 0x40091B: main (main.c:25) 
==25710== 
==25710== Invalid write of size 8 
==25710== at 0x400ABA: tokenize_string (functions.c:29) 
==25710== by 0x400953: main (main.c:29) 
==25710== Address 0x51c3048 is 0 bytes after a block of size 8 alloc'd 
==25710== at 0x4C27A2E: malloc (vg_replace_malloc.c:270) 
==25710== by 0x40091B: main (main.c:25) 

が示されています。

// EDIT

int main(int argc,char *argv[]) 
{ 
    int max_lines = atoi(argv[1]); 
    char *input_lines[max_lines]; 
    char **tokens; 
    char *output_string; 
    int token_index; 
    tokens=malloc(sizeof(char*)); 

    get_input(max_lines,input_lines); 
    token_index = tokenize_string(max_lines,input_lines,tokens); 
    output_string= concat_string(tokens,output_string,token_index); 
    print_string(output_string); 
} 

void get_input(int max_lines,char *input_lines[max_lines]) 
{ 
    int index; 
    printf("Enter %d lines",max_lines); 

    for(index = 0; index < max_lines;++index) 
    { 
     input_lines[index] = malloc(sizeof(char*)); 
     fgets(input_lines[index],50,stdin); 
    } 
} 

任意の提案ですか?あなたはポインタのためのスペースを割り当て、tokens[token_index]に割り当てる最初に

tokens[token_index] = malloc(sizeof(char*)); 
tokens[token_index] = token; 

+4

'tokens [token_index] = malloc(sizeof(char *));'は不要です(値は次の行に上書きされます)。この関数を呼び出すコードを提供できますか?あなたは '**トークン 'のために何を渡していますか? –

+2

「トークン」として渡されるものは何ですか?どのように定義され、初期化されていますか? – alk

+1

'main.c:25'と' ...:29'のコードと、 'functions.c:28'と' ..:29'のコードを知ることも興味深いでしょう。私の水晶球は壊れています。 – alk

答えて

2

は、次の2行を詳しく見てみましょうありがとうございます。次の行tokens[token_index]どこか別の点を指すように、mallocによって返されたポインタを失う。それは

i = 5; 
i = 10; 

をやっそしてi5ない理由疑問に、(それi名をすることができます)int変数を持つよりも違いません。

呼び出し元の関数でtokensの寿命がinput_linesの寿命に比べて小さい(または等しい)であるなら、あなたはここにメモリを割り当てる必要はありません、tokenからの割り当て(2行目は)十分です。


他にもtoken_indexが増えないような問題があります。

「無効な書き込み」に関しては、この機能がどのように呼び出されるかを示す適切なMinimal, Complete, and Verifiable Exampleがないと何も言い難いです。

+0

私はtoken_indexの値を必要に応じて増分していましたトークンの総数を知ること – Meghana

1

malloc()では、ポインタ自体にスペースを割り当ててから、それを指すように値を割り当てています。次の行は、それを上書きします。

この関数の存続期間の後にトークンの配列としてトークンを使用する必要があると仮定すると、あなたが探しているものは次のとおりです。トークンに含まれる文字列のスペースをtokens配列に作成し、それをコピーします。

int tokenize_string(int max_lines,char *input_lines[max_lines],char **tokens) 
{ 
    char *token; 
    int index,token_index=0; 

    for(index = 0; index < max_lines;++index) 
    { 
     token = strtok(input_lines[index]," "); 

     while(token != NULL) 
     { 
      size_t len = strlen(token) + 1; 
      tokens[token_index] = malloc(len); 
      strcpy(tokens[token_index], token); 
      token = strtok(NULL," "); 
     } 
    } 
    return token_index; 
} 

はまた、あなたはループのどこかでそれを変更しない限り、この機能は、ちょうど同じtoken_indexを上書きすることに注意してください。 tokens[]は、作成する必要がある文字列へのポインタのすべてに適合できることも確認する必要があります。


編集

さて、私は最初から開始し、ダウン私のように動作しますが、私は信じているよう

tokens=malloc(sizeof(char*)); 

は、文字列へのポインタの配列を作成されていませんよあなたは期待している。これはちょうどtokenscharへの単一のポインタのための十分なスペースを持つメモリの領域を指していると言います。あなたが指し示す予定の文字列のあらかじめ定義された最大数か、それを事前に知る方法を見つける必要があります。あなたは新しい文字列のためのスペースを作成してみますが、charを指すポインタにこのちょうどポイントする

input_lines[index] = malloc(sizeof(char*)); 

を使用thing-- get_input()

は、あなたが同様のをやっています。あなたのfgets()コール、および50文字に制限を考えると、あなたは単にあなたがあなたの50文字のためのスペースを持っているように、

input_lines[index] = malloc(50); 

を行うことができます。その後、ヌル終端文字列であることを確認する必要があります。

取り除く最も重要なことは、malloc(sizeof(char *))ではなく、です。文字列にスペースを割り当て、ポインタ用にスペースを割り当てます。これらは同じではないので、もう少し詳しく読むことをお勧めしますhere

本質的に、割り当てているメモリの範囲外で書いているようです。

+2

'sizeof(char)'は定義上1であるため、その冗長性を取り除くことができます。保存側に留まる場合は、 'sizeof * tokens [token_index]'で置き換えてください。 – alk

+0

この関数では、 'strtok'を使用しているときに私のアドレスが範囲外になるように入力する文字列の数はありません。 – Meghana

+0

コマンド行から最大行数を入力し、長さが不明な入力行を取り、トークン化しています。 – Meghana

関連する問題