2012-04-13 16 views
1

ファイルを文字列に読み込んで古いプログラムから文字列を出力するコードをコピーしました。それは問題なく動作していたので、少し修正することにしました。新しいプログラムは変数に代入すると完全に関係のない関数でセグメンテーションフォールトが発生する

#include <stdio.h> 
#include <string.h> 

int main() { 
    FILE *itemlist = fopen("itemlist", "r"); 
    char *currentstring, charbuffer[2]; 
    // char itemstart = 0; 
    while (fgets(charbuffer, 2, itemlist)) { 
     strcat(currentstring, charbuffer); 
    } 
    printf("%s", currentstring); 
    return 0; 
} 

です。期待どおりに動作します。しかし、itemstart行のコメントを外すと、セグメント化エラーが発生します。私もそれを使用していないと私の限りでは、0にcharを初期化することは違法ではありません。私はそれが型の問題だと思っていましたが、それを短いものに変更してからintに変更しましたが、それでもなおsegfaultを与えていました。

しかし、私は= 0の部分を取り除きました、そして、それは再び働きました。その後、gdbでバイナリをデバッグし、segfaultはstrcatになりました。

これはどのように可能ですか?

+0

「currentstring」は何を指していますか? – geekosaur

+0

現時点では何も表示されていませんが、空の文字列です。 'currentstring'をNULLにすると、segfaultsになります。 – user1002327

+2

それは修辞的だった。あなたは正しい、それは*何も指していない*。ランダムなメモリ。ランダムなメモリを変更するとどうなると思いますか?あなたはどこにそれを指し示すつもりだったと思いますか? – geekosaur

答えて

4

currentstringはダングリングポインタであるため、strcat(currentstring, charbuffer);の結果は未定義の動作になります。

char itemstart = 0のコメントを外すとメモリが0に初期化され、アクセス違反が表示されますが、これはまあまあです。未定義の動作は何かが起こる可能性があることを意味

あなたはcurrentstringにメモリを割り当てる必要があります。

currentstring = malloc(10); //or whatever length you need 
+0

コードを訂正しましたが、あなたは彼の質問に答えませんでした:) –

+0

これは 'id = [name、properties、...]'という形式のitemlistを読み込むプログラムになりますので、各行の長さ10または150になる可能性があります。 – user1002327

+0

@EldritchConundrumでした。未定義の動作。答えをもう一度読んでください。 –

1

currentstringのスペースを割り当てる必要があります。

1

コメント解除無関係なラインがC言語のunsafenessによって可能になっているセグメンテーションフォールト。間違ったプログラムの終了動作は、コンパイラによって行われた微妙な選択によって決まります。

このような狂気に直面した場合は、まずコードを修正してください。これはもちろん、必ずしも容易ではありません。 8行のプログラムでは、あなたは大丈夫でしょう。

1

currentstring変数に領域を割り当て、セグメントの障害/ヒープの破損を避けるために、そのサイズを制御する必要があります。

#define MAX_BUFFER_SIZE 32 
//... 
FILE *itemlist = fopen("itemlist", "r"); 
char *currentstring = malloc(MAX_BUFFER_SIZE+1); 
char *tmpbuf; 
char charbuffer[2]; 
// char itemstart = 0; 
int bytesloaded = 0; 
while (fgets(charbuffer, 2, itemlist)) { 

    if(bytesloaded + 2 > buf_size) { 
     /* call realloc() */ 
     buf_size += MAX_BUFFER_SIZE; 
     tmpbuf = realloc(currentstring, buf_size); 
     if(tmpbuf == NULL) { /* Get off loop. Using break or return. */ 
      break; 
     } 
     currentstrig = tmpbuf; 
    } 
    memcpy(currentstring + bytesloaded, charbuffer, 2); 
    bytesloaded += 2; 
} 
//... 
free(currentstring); 

私はテストしていませんが、動作すると思います。

関連する問題