9

32x32 16bpp画像を定数値(1024)で埋めるための非常に単純なコードを作成しました。画像バッファはによってホストされますstd::vector。画像のピッチ/ストライド(つまり、2つの連続する行の間のバイト数)は、行全体を保持するのに十分な大きさですが、奇数に設定されています。これが私のコードです:

#include <vector>
#include <stdint.h>

int main()
{
  int width = 32;
  int height = 32;
  int pitch = width * 2 + 1;

  std::vector<uint8_t> image(height * pitch);
  uint8_t* buffer = &image[0];

  for (int y = 0; y < height; y++)
  {
    uint16_t* p = reinterpret_cast<uint16_t*>(buffer + y * pitch);
    for (int x = 0; x < width; x++, p++)
    {
      *p = 1024;
    }
  }
}

Linuxx86_64とgcc4.6.1(Ubuntu 11.10)を使用しています。コードは、、および最適化レベルで正常に実行さ-O0-O1ます-O2。Valgrindはアクセス違反を報告しません。ただし、自動ベクトル化のオプションに切り替える-O3か使用するとすぐに、プログラムがクラッシュします。-ftree-vectorize

# g++ -g -O3 ./test.cpp -Wall -pedantic && ./a.out
Segmentation fault

# g++ -g -O2 -ftree-vectorize ./test.cpp -Wall -pedantic && ./a.out
Segmentation fault

gdbもvalgrindも有用な情報を提供しません:

# valgrind ./a.out
==3840== Memcheck, a memory error detector
==3840== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==3840== Using Valgrind-3.6.1-Debian and LibVEX; rerun with -h for copyright info
==3840== Command: ./a.out
==3840== 
==3840== 
==3840== Process terminating with default action of signal 11 (SIGSEGV)
==3840==  General Protection Fault
==3840==    at 0x4005B3: main (test.cpp:18)
==3840== 
==3840== HEAP SUMMARY:
==3840==     in use at exit: 2,080 bytes in 1 blocks
==3840==   total heap usage: 1 allocs, 0 frees, 2,080 bytes allocated
==3840== 
==3840== LEAK SUMMARY:
==3840==    definitely lost: 2,080 bytes in 1 blocks
==3840==    indirectly lost: 0 bytes in 0 blocks
==3840==      possibly lost: 0 bytes in 0 blocks
==3840==    still reachable: 0 bytes in 0 blocks
==3840==         suppressed: 0 bytes in 0 blocks
==3840== Rerun with --leak-check=full to see details of leaked memory
==3840== 
==3840== For counts of detected and suppressed errors, rerun with: -v
==3840== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)
Segmentation fault

-m32gccフラグを指定して32ビットバイナリに切り替えても、クラッシュは発生しません。偶数ピッチ(例)を使用しても発生しませんpitch = width * 2 + 2。誰かが私が私のコードで作った(確かに愚かな)エラーを見つけるのを手伝ってもらえますか?よろしくお願いします!


更新: Jonathanが提案したように、私はこの問題をGCC開発者に報告しました:http: //gcc.gnu.org/bugzilla/show_bug.cgi? id = 56392

4

1 に答える 1

4

私の質問は、 gcc Bugzillaで Richard Blener によって回答されました。

「その型に対して十分にアラインされていない uint16_t へのポインターを逆参照しています。C 標準ではこれが禁止されているため、未定義の動作が発生します。」

ただし、私の意見では、この未定義の動作について警告を生成する必要があります。この説明は、この投稿へのコメントで @jmetcalfe によって提供されたことにも注意してください。

于 2013-02-19T12:10:57.870 に答える