2012-01-18 13 views
4

最初に私はC言語ではかなり新しいので、ここでは基本的な誤解があるかもしれません。このようなコードを考える:特定のサイズの文字配列

(gdb) p ack 
$1 = "testing\000\360WV\000\000\000\000\000\277\000\000\000\000\000\000  
'\000'\000\220\[email protected]",<repeats 13 times>, "\003\[email protected]", '\000' <repeats 13 times>  
"\325,\[email protected]\000\000\000\000\000H\214\246\367\377\177\000\000\220\[email protected]", 
'\000' <repeats 13 times>,  "P\[email protected]\000\000\000\000\000\360\342\377\377"` 

これは私がackを初期化する方法を与えられた私には理にかなって:GDBによって調べたときに

int main() 
{ 
    char ack[100]; 
    char *bar; 
    bar = malloc(100); 
    strncpy(ack, "testing", 7);  
    bar = "testing"; 

    return 0; 
} 

ackすると、このようになります。

(gdb) p bar 
$2 = 0x40066c "testing" 

私はackのためのスペースを要求したとき、私は私が行ったように(私の知る限り)ストレージのと同じ量を割り当てたが、malloc関数がありません:barはこのようになりますなぜ私は非常に得ることはありませんことです余分な迷惑。私が理解しているように、mallocはデータの初期化など何もしないので、少し混乱します。これが現れた理由は、私がstrstrで持っていた問題です。基本的に、ファイル(fgets)から特定のサイズのchar配列にデータを読み込むと、strstr()は失敗します(余分な迷惑メールが原因であると仮定していました)。ポインタとmallocされたメモリの作業はうまくいった。とにかく、いくつか具体的な質問があります。

  1. このmallocされた変数の動作は予期されていますか?ここでいくつかの最適化が行われていますか(gccでコンパイルされましたが、最適化はしていませんでした)、gdbはすべてを表示していませんか?その変数に関連する「迷惑メール」が存在するはずですか?

  2. mallocを正しく使用していますか?私が要求したすべてのメモリを初期化する必要がありますか?もしそうなら、どうですか?

ありがとうございます!答えみんなに

EDIT

ありがとう!私はあなたからすべてかなりのことを学びました。そしてそれは大いに感謝しています。上記のコードで問題が発生し、fgets()とstrstr()で問題が発生していました。

+0

メモリは、割り当て時にヌルで埋められません。それを行うにはmemset(..) – Adrian

+2

@Adrian、いいえ、いいえ。これは 'C'です。 'malloc()'をキャストしてはいけません。 'C 'に新しいことを教えてはいけません。 –

+0

@DanFego私はあまりにも私はhahaを推測して学習しています。私はいつもmallocsをキャストしてきました。情報をありがとう。私は私のコメントを編集しました! – Adrian

答えて

10
bar = "testing"; 

ストリング"testing"、あなたmalloc D「配列にすなわち、それはもはやポイントを保持する静的バッファを指すようにポインタbarを再度割り当てます。これはmemory leakです。

あなたはackで行ったように、strcpystrncpyまたはmemcpyを使用し、malloc「Dバッファに文字列を取得します。

+3

余分な+1は、メモリリークだと指摘しています。 – cdeszaq

2

リテラルともはや(漏れた)malloc EDメモリに文字列をbarポイントになります

bar = "testing"; 

を割り当てるときに(意図せず)malloc EDメモリを捨てるためです。

+0

「malloc」の記憶を「捨てる」よりむしろ「忘れる」と言うでしょう。 – cdeszaq

+0

「捨てる」には意思の意味があるので、それは「忘れる」ためのポイントです。一方、「忘れる」はメモリリークのために十分に劇的には聞こえません。私は妥協しました。 –

+0

パーフェクト!私たちはまた、 "失う"、 "漏れ"、 "落とす"、 "無視する"、そして "宇宙の捨て場として捨てる"と受け入れたでしょう。 – cdeszaq

-1

C文字列にはヌルターミネータ(ASCII文字値0)があり、C文字列 "testing"は実際にターミネータを含めて8バイトです。

元の値を印刷すると、ターミネータに達すると印刷が停止します。

最初の7文字しかコピーしなかったので、2番目の値を印刷すると、前にあったガベージデータのゼロに達するまで迷惑をかけています。

+0

また、ダニエルの説明だったかもしれません;-)それは技術的には本当ですが、私はダウンボートに値するとは思わない。 –

0

あなたはいくつかの点で中止しています。

最初に、理由が「テスト」の後に「テスト」の後にゴミがあるのは、決してヌル終了しなかったからです。 Cでは、すべての文字列はNULLで終了する必要があります。つまり、末尾は\0です。あなたは、どちらかの長さ8(strlen("testing") + 1) or just usingのstrcpy()でstrncpy()を呼び出すことで、ここでこの問題を解決することができます。ackはストレートアップchar配列である一方で、それは、charへのポインタですので、第二に、bargdbに違って見える

gdbはあなたを示していbarのポインタ値ですが、できる限りポインタの反対側にあるものを表示することで、あなたが好きになります。bar = "testing;"を実行すると、barが何を指しているのかを再割り当てします。このような文字列リテラルを使用すると、末尾に自動的に\0文字があるため、NULLで終了します。その後はゴミが出ない。

関連する問題