1

アプリケーションで memcpy を使用しています。memcpy はランダムにクラッシュします。以下は Dr.Watson ファイルで取得したログです。

        100181b5 8bd1             mov     edx,ecx
        100181b7 c1e902           shr     ecx,0x2
        100181ba 8d7c030c         lea     edi,[ebx+eax+0xc]
        100181be f3a5             rep     movsd
        100181c0 8bca             mov     ecx,edx
        100181c2 83e103           and     ecx,0x3
FAULT ->100181c5 f3a4             rep     movsb  ds:02a3b000=?? es:01b14e64=00
        100181c7 ff1508450210     call    dword ptr [Debug (10024508)]
        100181cd 83c424           add     esp,0x24
        100181d0 6854580210       push    0x10025854
        100181d5 ff1508450210     call    dword ptr [Debug (10024508)]
        100181db 83c404           add     esp,0x4

以下はコードです

memcpy((char *)dep + (int)sizeof(EntryRec) + (int)adp->fileHdr.keySize, data, dataSize ); 

どこ:

  • dep は構造体です
  • EntryRec は文字ポインタです
  • adp は構造体です
  • データはNULLこの場合ではありません

誰かがこの問題に直面していて、私を助けることができますか?

私はプログラムをデバッグしようとしましたが、次のエラーが発生しました。

データはこのプログラムの引数に渡され、これは void* です

詳細情報:

コード アダプターをデバッグしようとしましたが、次の領域でクラッシュしています。この関数は OUTPUT.c にあります (これはライブラリ関数だと思います)。

#else  /* _UNICODE */
            if (flags & (FL_LONG|FL_WIDECHAR)) {
                if (text.wz == NULL) /* NULL passed, use special string */
                    text.wz = __wnullstring;
                bufferiswide = 1;
                pwch = text.wz;
                while ( i-- && *pwch )
                    ++pwch;
                textlen = pwch - text.wz;
                /* textlen now contains length in wide chars */
            } else {
                if (text.sz == NULL) /* NULL passed, use special string */
                    text.sz = __nullstring;
                p = text.sz;
                while (i-- && *p) //Crash points here
                    ++p;
                textlen = p - text.sz;    /* length of the string */
            }

変数の値: p= ""(初期化されていない) i= 2147483598

4

7 に答える 7

16

2つの非常にありそうな説明があります:

  1. 重複するアドレス間で使用memcpyしています-この状況の動作は定義されていません。重複するアドレスを処理する機能が必要な場合std::memmoveは、「同等の」ツールです。
  2. memcpyプログラムにアクセスできないメモリとの間でコピーするために使用しています。

示したコードから、(2)がより可能性の高いシナリオであるように見えます。ソースをデバッグできるので、発生する前にブレークポイントを設定してみて、すべての引数が一致memcpyすることを確認してください(つまりまたは)。memcpysource + num < destsource > dest + num

于 2009-10-15T11:29:23.927 に答える
10

逆アセンブルされたコードから、ソース ポインターがアドレス空間にないように見えます。rep movsb は ds:si から es:di にコピーします。?? ds:si のメモリを読み取れなかったことを示します。

于 2009-10-15T11:40:43.933 に答える
1

バッファの終わりを超えてアクセス違反が発生したようです。

編集:まだ十分な情報がありません。コピーしようとしているバッファに十分なスペースがあるかどうか(おそらくない)、およびdataSizeが有効であるかどうかについて、詳細を知らなければ、バグを見つけることはできません。

于 2009-10-15T11:27:19.593 に答える
1

memcpyがクラッシュする場合、通常の理由は、不正な引数を渡したことです。

memcpyでは、送信元と宛先が重複しない場合があることに注意してください。

このような場合は、memmoveを使用してください。

于 2009-10-15T11:29:01.820 に答える
1

コード「memcpy((char *)dep + (int)sizeof(EntryRec) + (int)adp->fileHdr.keySize, data, dataSize)」とデバッグ情報から、「データ」はローカル変数のように見えます(オンスタック変数)、「char data[DATA_SIZE]」などの代わりに「data = malloc(DATA_SIZE)」を実行します。そうしないと、現在のコード行で「データ」がすでにポップされているため、ランダムにメモリ アクセス エラーが発生する可能性があります。

于 2009-10-15T11:59:54.240 に答える
1

が指すデータは(char *)dep + (int)sizeof(EntryRec) + (int)adp->fileHdr.keySize常に少なくともdataSize長いですか?

可変長文字列が後で文字列で固定されたように扱われる同様のクラッシュに遭遇しました。

例えば

char * ptr = strdup("some string");
// ...
memcpy(ptr, dest, fixedLength);

fixedLengthは より大きいです10。明らかに、これらは異なる機能にあったため、長さの問題は認識されませんでした. ほとんどの場合、これは機能し、dest「何らかの文字列」が含まれ、null の後にはランダムなガベージになります。この場合、dest を null で終了する文字列として扱うと、null の後にゴミが表示されないため、気付くことはありません。

ただしptr、メモリのページの最後に割り当てられている場合は、割り当てられたメモリの最後までしか読み取ることができず、それ以上は読み取れません。ページの終わりを過ぎて読むとすぐに、オペレーティング システムは当然のことながらプログラムをクラッシュさせます。

于 2009-10-15T12:59:53.343 に答える
0

この状況でmemcpyを使用すると、結果が予測できないため、重複する文字列を処理するため、memmoveを使用することをお勧めします。

于 2009-10-15T11:30:13.800 に答える