2016-11-09 3 views
1

私は非常に単純なプログラムで問題を抱えていましたが、なぜそれは本当にわかりません。連絡先のリストを意味し、別の構造体があり、連続スキャンで文字列を追加しています

typedef struct { 
    char name[50]; 
    char p_id[11]; 
    char cel[11]; 
    int by; 
    int id; 
} Person; 

:そこの人のための構造体がある

typedef struct { 
    Person * people; 
} lContacts; 

私はそれに人のデータを含めるようにしようとしてきた、とその人を連絡先リストに追加します。人は、通常は追加されているので、私はここにコードを投稿しませんが、私は、文字列を読んだときに何か間違った出来事があります:私は私が記載されているときので、私は、そこに印刷テストを持っていることを

void include(lContacts * myContacts) 
{ 

    Person p; 

    scanf("%s", p.name); 
    scanf("%d", &p.by); //birth year 
    scanf("%s", p.p_id); 
    printf("TEST P_ID: %s\n\n", p.p_id); 
    scanf("%s", p.cel); 
    printf("TEST P_ID AGAIN: %s\n\n", p.p_id); 

    myContacts->people[index]=p; //don't worry about the index, there is a piece of code I'm omitting to make it easier to read, just assume it is right. 
    } 
} 

お知らせ連絡先p_idcelと連結していたので、間違いが見つかるまでコード全体を印刷しました。

Name 
1991 
11111111111 
<console prints| TEST P_ID: 11111111111> 
22222222222 
<console prints| TEST P_ID AGAIN: 1111111111122222222222> 

私はp.celを印刷する場合は、それが正しく印刷され

<console prints 22222222222> 

任意のアイデア:ここ

は入力例ですか?文字列をスキャンするときに '&'を使用する必要がありますか? (私はそれについて、私が理解した方法を読んで、必要はありません。それは正しいのですか?)

+2

Cの文字列は、NUL文字(別名「\ 0」)で終わる 'char'の配列で構成されています。 'p_id'配列は11バイトなので、10桁とNULだけを格納できます。つまり、バッファオーバーランのバグがあります。 – user3386109

+1

ie - pidをchar [12]に変更する(11がpidの最大長である場合) – pm100

答えて

1

これは実際にはここでは非常に間違いです。基本的に、文字列p.p_idバッファオーバーフローが発生しています。

あなたが入力した値がp.p_id11111111111として(11回1)のために、あなたはp_id文字列の実際の容量は、最後にNULL文字が含まれている必要がありちょうど11として宣言されていることを認識しなければならない

11111111111p_idを割り当てると、その文字列にNULL文字が残っていないため、その最後には何も挿入されません。

構造体の次のメンバーストリングの値を入力すると、同じことも起こります。

p.p_idの値を印刷しようとすると、文字列に'\0'(NULL文字)が見つかるまで値が印刷されます。しかし、ここには何もないので、次の文字列が印刷を開始します! (バッファまたは文字列p_idがオーバーフローする)

これは、Cの構造体でメンバの位置合わせが行われたために発生します。次の文字列は連続したメモリセルに格納され、印刷が続行されます。 (3番目の連続した文字列メンバがあった場合、2番目の文字列にバッファオーバーフローが発生しても印刷されます)

しかし、2番目の文字列の後に印刷が停止するのは、次の連続するメモリセルが特定の構造体の整列のために存在するか、またはNULL文字として解釈される次のセルに実際の0値が存在する可能性があります。

文字配列に大きなサイズを使用するか、動的に割り当てられた文字列を使用しないでください。

+0

ありがとう –

0

@skrtbhtngrが指摘しているように、バッファオーバーフローが発生しています。これを未然に防止するには、未知の文字列入力に対してscanfの代わりにfgetsを使用する必要があります。入力が壊れている場合、この例はexit(1)になります。

int getsafestring(char* s, int maxlen) 
{ 
    if(fgets(s,maxlen,stdin) == NULL) return 1; // read error 
    if(strlen(s) == 0) return 2; // other read error 
    if(s[strlen(s)-1] !='\n') return 3; // buffer overflow error 
    s[strlen(s)-1]=0; // replace newline with null 
    return 0; 
} 

if(Getsafestring(p.name,sizeof(p.name))) exit(1); 
if(scanf("%d", &p.by) != 1)    exit(1); 
if(getsafestring(p.p_id,sizeof(p.p_id))) exit(1); 
if(getsafestring(p.cel,sizeof(p.cel))) exit(1); 
関連する問題