4

memset(). _ 問題は、コードが数日間実行されていない限り、通常は発生しないため、その行為を把握するのが難しいことです。

私は次のコードを使用しています:

char *msg = (char*)malloc(sizeof(char)*2048);
char *temp = (char*)malloc(sizeof(char)*1024);
memset(msg, 0, 2048);
memset(temp, 0, 1024);
char *tempstr = (char*)malloc(sizeof(char)*128);

sprintf(temp, "%s %s/%s %s%s", EZMPPOST, EZMPTAG, EZMPVER, TYPETXT, EOL);
strcat(msg, temp);

//Add Data
memset(tempstr, '\0', 128);
wcstombs(tempstr, gdevID, wcslen(gdevID));
sprintf(temp, "%s: %s%s", "DeviceID", tempstr, EOL);
strcat(msg, temp);

ご覧のとおり、最初に割り当てられたサイズよりも大きいサイズの memset を使用しようとはしていませんmalloc()

これで何が問題なのか誰にもわかりますか?

4

10 に答える 10

21

mallocNULLメモリが利用できない場合に戻ることができます。あなたはそれをチェックしていません。

于 2008-08-22T14:21:43.030 に答える
4

いくつかのことがあります。sprintf本質的に安全でないものを使用しています。バッファのサイズを超えないことを 100% 確信していない限り、ほとんどの場合snprintf . strcat同じことが;にも当てはまります。より安全な代替手段を好むstrncat

明らかに、これで何も解決しない可能性がありますが、そうでなければバグを見つけるのが非常に煩わしいものを見つけるのに大いに役立ちます

于 2008-08-22T14:26:14.860 に答える
3

メモリが利用できない場合、malloc は NULL を返すことができます。あなたはそれをチェックしていません。

そうですね... メモリを監視していて、十分な空きがあったので、それについては考えていませんでした。システムに利用可能なメモリがあるが、malloc が失敗する方法はありますか?

はい、メモリが断片化されている場合。また、「メモリの監視」と言うと、時折大量のメモリを消費し、気付かないうちにメモリを解放する何かがシステム上にある場合があります。への呼び出しがmalloc発生した場合、使用可能なメモリはありません。--ジョエル

いずれにせよ...私はそのチェックを追加します:)

于 2008-08-22T14:26:28.930 に答える
1

wcstombs doesn't get the size of the destination, so it can, in theory, buffer overflow.

And why are you using sprintf with what I assume are constants? Just use:

EZMPPOST" " EZMPTAG "/" EZMPVER " " TYPETXT EOL

C and C++ combines string literal declarations into a single string.

于 2008-08-22T16:31:49.317 に答える
0

mallocの後にを実行する代わりに、新しく割り当てられたメモリをクリアするmemsetを使用する必要があります。callocそれ以外は、ジョエルが言ったことをしてください。

于 2008-09-20T06:46:06.337 に答える
0

NBは他の回答からいくつかのコメントを借りて、全体に統合しました。コードはすべて私のものです...

  • エラーコードを確認してください。たとえば、利用可能なメモリがない場合、malloc は NULL を返すことができます。これにより、データが中断される可能性があります。
  • sizeof(char) は定義上 1 です
  • sprintf ではなく snprintf を使用してバッファ オーバーランを回避する
    • EZMPPOST などが定数である場合、フォーマット文字列は必要ありません。複数の文字列リテラルを STRING1 " " STRING2 " " STRING3 および strcat 全体として組み合わせることができます。
  • 必要以上のメモリを使用しています。
  • マイナーな変更が 1 つあるだけで、そもそも memset を呼び出す必要がなくなりました。ここでは、初期化をゼロにする必要はありません。

このコードは、同じことを安全に実行し、実行速度が速く、メモリの使用量が少なくなります。

    // sizeof(char) is 1 by definition. This memory does not require zero
    // initialisation. If it did, I'd use calloc.
    const int max_msg = 2048;
    char *msg     = (char*)malloc(max_msg);
    if(!msg)
    {
       // Allocaton failure
       return;
    }
    // Use snprintf instead of sprintf to avoid buffer overruns
    // we write directly to msg, instead of using a temporary buffer and then calling
    // strcat. This saves CPU time, saves the temporary buffer, and removes the need
    // to zero initialise msg.
    snprintf(msg, max_msg, "%s %s/%s %s%s", EZMPPOST, EZMPTAG, EZMPVER, TYPETXT, EOL);

   //Add Data
   size_t len = wcslen(gdevID);
   // No need to zero init this
   char* temp = (char*)malloc(len);
   if(!temp)
   {
      free(msg);
      return;
   }
   wcstombs(temp, gdevID, len);
   // No need to use a temporary buffer - just append directly to the msg, protecting 
   // against buffer overruns.
   snprintf(msg + strlen(msg), 
           max_msg - strlen(msg), "%s: %s%s", "DeviceID", temp, EOL);
   free(temp);
于 2008-09-24T17:55:39.983 に答える
0

それはあなたのプロセッサーかもしれません。一部の CPU は単一バイトをアドレス指定できず、ワードまたはチャンク サイズで作業するか、ワードまたはチャンク アラインされたデータでのみ使用できる命令を使用する必要があります。

通常、コンパイラはこれらを認識して回避しますが、領域をバイトとして malloc し、それを構造体またはバイトよりも広いフィールドとしてアドレス指定しようとすると、コンパイラはそれをキャッチしません。 、ただし、プロセッサは後でデータ例外をスローします。

特殊な CPU を使用していない限り、これは発生しません。たとえば、ARM9 はそれを行いますが、i686 は行いません。Windows Mobile とタグ付けされているので、この CPU に問題がある可能性があります。

于 2008-09-20T06:40:13.947 に答える
0

Valgrindを使ってみましたか?これは通常、これらの種類のエラーをデバッグするための最も速くて簡単な方法です。割り当てられたメモリの範囲外で読み取りまたは書き込みを行っている場合は、フラグが立てられます。

于 2008-08-22T14:18:58.433 に答える
0

本質的に安全でない sprintf を使用しています。バッファーのサイズを超えないことを 100% 確信している場合を除き、ほとんどの場合、snprintf を使用する必要があります。同じことが strcat にも当てはまります。より安全な代替 strncat を優先します。

うん..... 最近は主に .NET を使っていますが、古い習慣はなかなか消えません。そのコードは、私の時間より前に書かれた別のものから引き出した可能性があります...

しかし、私は将来それらを使用しないようにします;)

于 2008-08-22T14:28:36.007 に答える
0

あなたのコードでさえないかもしれないことを知っています...メモリリークを起こす可能性のある実行中の他のプログラムはありますか?

于 2008-08-22T14:28:47.147 に答える