在用-O3优化和奇数音高填充16bpp图像时崩溃
Crash while filling a 16bpp image with -O3 optimization and odd pitch
我写了一个非常简单的代码,用常数值(1024)填充一个32x32 16bpp的图像。图像缓冲区由CCD_ 1托管。我的图像的间距/步幅(即两个连续行之间的字节数)足够大,可以容纳整行,但设置为奇数。这是我的代码:
#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;
}
}
}
我使用的是Linux x86_64和gcc 4.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
当我切换到带有-m32
gcc标志的32位二进制文件时,不会发生崩溃。如果我使用偶数音高(例如pitch = width * 2 + 2
),也不会发生这种情况。有人能帮我发现我在代码中犯的(当然是愚蠢的)错误吗?非常感谢!
更新:正如Jonathan所建议的,我刚刚向GCC开发人员报告了这个问题:http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56392
我的问题已经由Richard Blener在gcc Bugzilla上回答:
您正在取消引用指向uint16_t的指针,该指针没有为该类型充分对齐。C标准禁止这样做,从而导致未定义的行为。
然而,在我看来,应该对这种未定义的行为发出警告。还请注意,@jmetcalfe在对这篇文章的评论中也给出了这一解释。
相关文章:
- 在c++中用vector填充一个简单的动态数组
- 如何使用用户输入在C++中正确填充2D数组
- 如何找到大小'x'数组是否完全填充,在C++?
- Cuda C++:设备上的Malloc类,并用来自主机的数据填充它
- 通过for循环使用用户输入填充列表
- 根据用户输入用字母填充矢量,并将"开始"和"结束"放在四肢
- 如何正确填充在堆上分配的二维数组?
- 将数字转换为填充字符串
- 有没有办法在一行中填充矢量图
- 用C++中的数字和条件填充向量
- 用真值填充矢量
- 使用结构成员指针在C++中填充结构
- 流填充字符的默认定位
- 使用不同算法的 PKCS1v15 填充进行加密 ++ 签名
- C++:使用缓冲区中的数据填充结构
- 如何将零填充的多维数组传递给 C++ 中的函数?
- Cryptopp:获取密码输入的填充字符串
- 填充上编译器生成的复制构造函数之间的不一致
- RcppEigen 模板化函数,用于填充单位法线
- 在用-O3优化和奇数音高填充16bpp图像时崩溃