13

私はこのバグを追いかけてきましたが、うまくいきません。基本的なCか何かを忘れましたか?

==28357== Conditional jump or move depends on uninitialised value(s)
==28357==    at 0x4C261E8: strlen (mc_replace_strmem.c:275)
==28357==    by 0x4E9280A: puts (ioputs.c:36)
==28357==    by 0x400C21: handlePath (myshell.c:105)
==28357==    by 0x400B17: handleInput (myshell.c:69)
==28357==    by 0x400AAD: acceptInput (myshell.c:60)
==28357==    by 0x4009CF: main (myshell.c:33)
==28357==  Uninitialised value was created by a heap allocation
==28357==    at 0x4C25153: malloc (vg_replace_malloc.c:195)
==28357==    by 0x400BDE: handlePath (myshell.c:99)
==28357==    by 0x400B17: handleInput (myshell.c:69)
==28357==    by 0x400AAD: acceptInput (myshell.c:60)
==28357==    by 0x4009CF: main (myshell.c:33)
==28357==

(095) void handlePath(char *input) {
(096)     if(DEBUG_ON) { printf("%s%s\n", "DEBUG_HANDLEPATH: ", input); }
(097)
(098)     char *inputCopy = NULL;
(099)     inputCopy = (char *)malloc((strlen(input)+1)*sizeof(char));
(100)
(101)     if(inputCopy==NULL) {
(102)         die("malloc() failed in handlePath()");
(103)     }
(104)     strncpy(inputCopy, input, strlen(input)*sizeof(char));
(105)     printf("%s\n", inputCopy);
(106)     free(inputCopy);
(107)     return;
(108) }

96行目はパラメーター"char* input"を正常に出力しますが(DEBUG_ON == 1)、105行目はvalgrindエラーを吐き出します(コンソールでは正常に出力されます)。「char*input」は、getline()が入力行を取得することで発生します。この関数の場合、引用符なしの「path / test/path」のようになります。前の関数でうまく印刷して操作できます。「char*inputCopy」について初期化されていないものは何ですか?何か案は?前もって感謝します!

4

3 に答える 3

13

104行目に2つの間違いがあります。

strncpy(inputCopy, input, strlen(input)*sizeof(char));

strncpyにnullを終了させる余地を与える必要があるため、strlen(input)+1 strncpyは出力バッファーをnullで終了したままにすることが保証されていないはずです。これは、strncpyのバグのように見えますが、そうではありません。それはそのように機能するように設計されました。strncpyが行うように設計されたのは、文字列を出力バッファーにコピーしてから、バッファーの残りの部分をゼロで埋めることでした。これは、実際には「安全なstrcpy」として設計されていません。

もう1つのバグは、strncpyがバイト数ではなく文字数sizeof(char).を取得するため、を掛けるのは正しくないということです。sizeof(char)== 1なので、これは実際には問題を引き起こしていませんが、それでも間違った意図です。

バイトカウントが必要なため、99行目sizeof(char)で乗算するのは正しいことです。mallocmalloc

于 2010-01-30T06:17:57.150 に答える
4

strncpyは、最大N文字(Nは3パラメーター)をコピーするため、終了0文字を入れません。長さを指定し、終了0の+1を含めなかったため、追加されませんでした。

したがって、Nバイトのバッファがあると仮定すると、strncpyの適切な使用法は次のとおりです。

strncpy(dest, src, N - 1);
dest[N - 1] = '\0';

strncpyは奇妙な関数です。終了0を書き込むことを約束しないことに加えて、それは常に正確にN文字を宛先バッファーに書き込みます。srcがNより小さい場合、strncpyは実際にはバッファの残り全体を0で埋めるのに時間がかかります。

于 2010-01-30T06:18:35.667 に答える
3

strncpy文字列の末尾にヌル文字を配置していないため、printf は割り当てられたメモリの末尾から実行されていると思います。

于 2010-01-30T06:13:02.667 に答える