1

「stringint」という行を含む標準的に入力されたテキストファイルを調べるプログラムをcで書いています。元々scanfでプログラムを正常に実行していましたが、名前は動的文字列(実行時に既知のサイズ)である必要があり、grade_entryの名前をポインターに切り替えると、セグメンテーション障害が発生しました。

typedef struct grade_entry {
       char *name;
       int grade;
} grade_entry;

struct grade_entry grade_list[100];

int main(){
    int grade;
    int done;
    int i=0;
    do{
            puts("not weee\n");
            done=(int)strlen(gets(grade_list[i].name));
            puts("weee\n");
    }while(1);
}

コンパイルされ、現在の出力は次のとおりです。

not weee

segmentation fault(core dumped)

**解決済み:ポインターを割り当ててから、size + 1に再割り当てし、最後にnullを追加しました。scanf、fgets、getsの一時メモリに基づいてすぐにmallocを実行できないのは残念です。まあ、みんな助けてくれてありがとう

4

4 に答える 4

4

にメモリを割り当てる必要がありますgrade_entry.name。そうしないと、任意のメモリ位置を指すcharポインタになり、そこに書き込むとセグメンテーション違反が発生します。

于 2012-12-18T06:29:55.713 に答える
1

char * nameフィールドにメモリを割り当てていませんが、実際には所有していない値をこのメモリに格納しています。

それに加えて、無限ループを実行し、同じ配列要素で遊んでいます(「i」をインクリメントしません)

以下は私が推測する動作するコードです。

typedef struct grade_entry {
   char *name;
   int grade;
} grade_entry;

int main(){
int grade;
int done;
char str[100];
grade_entry grade_list[10];
int i=0;    
do{
        puts("not weee\n");
        gets(str);
        grade_list[i].name=(char*)malloc(strlen(str));
        done=strlen(grade_list[i++].name);
        puts("weee\n");
  }while(i<10);
}
于 2012-12-18T06:37:04.140 に答える
1

欠点はここにあります:

        done=(int)strlen(gets(grade_list[i].name));//Storing in a unallocated memory using an uninitialized pointer. BAD!

あなたのコードのほかに、の値をインクリメント/デクリメント/変更することはどこにも見当たりませんi。したがって、基本的にはgrade_list[0].name、ループが実行されるたびに上書きされます。それも悪いです。メモリリークが多すぎます!!

そして、ブレーク条件のない無限ループです!

次のようなものを試してください。

char buffer[MAX_LENGTH_OF_A_STRING];
memset(buffer,0x00,MAX_LENGTH_OF_A_STRING);
do{
        puts("not weee\n");
        done=strlen(gets(buffer));//This is enough
        grade_list[i].name=malloc(strlen(buffer)+1);
        strncpy(grade_list[i].name,buffer,strlen(buffer)+1);
        memset(buffer,0x00,MAX_LENGTH_OF_A_STRING);
        i++;//You were not doing this
        puts("weee\n");
        //Put some condition to break this infinite loop, somewhere within the loop
}while(1);
于 2012-12-18T06:40:24.907 に答える
1

使用しないでくださいgets()—これまでに。存在しないふりをします。あなたがそれを使うならば、それがあなたのコンピュータを爆破するふりをしてください。プログラムをクラッシュさせるために使用されると想定します—そうなるからです。

問題は、gets()どのくらいのスペースで作業する必要があるかがわからないことです。

fgets()代わりに使用してください。長い行の読み取りが心配な場合は、システムgetline()に任意の長さの行の読み取りを処理するPOSIX2008関数があることを期待する必要があります。処理する必要があるのは文字ポインタの配列だけで、これはより簡単です。

プログラムでは、ポインタはデータ構造内のポインタにコピーされることになります。

それはすべて良いきれいな楽しみです。重要なことは、ポインターを初期化していない場合、ポインターはランダムにポイントし、ポインターが何を指しているのかがわかるまで、ポインターを安全に使用できないことを覚えておくことです。したがって、ポインタを初期化してどこかを指すようにするか、NULLを初期化してどこも指さないことを示します。NULLポインタを逆参照しないでください。

于 2012-12-18T06:54:14.727 に答える