Tôi đã viết một mã rất đơn giản để lấp đầy hình ảnh 32b32 16bpp với giá trị không đổi (1024). Bộ đệm hình ảnh được lưu trữ theo số std::vector
. pitch/stride hình ảnh của tôi (nghĩa là số byte giữa hai dòng liên tiếp) đủ lớn để giữ toàn bộ dòng, nhưng là đặt số lẻ. Đây là mã của tôi:Sụp đổ trong khi điền hình ảnh 16bpp với tối ưu hóa -O3 và độ cao lẻ
#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;
}
}
}
Tôi đang sử dụng Linux x86_64 với gcc 4.6.1 (Ubuntu 11.10). Mã chạy tốt với các mức tối ưu hóa -O0
, -O1
và -O2
. Valgrind không báo cáo bất kỳ vi phạm truy cập nào. Tuy nhiên, ngay sau khi tôi chuyển sang -O3
hoặc sử dụng tùy chọn -ftree-vectorize
để tự động vector, chương trình bị treo:
# g++ -g -O3 ./test.cpp -Wall -pedantic && ./a.out
Segmentation fault
# g++ -g -O2 -ftree-vectorize ./test.cpp -Wall -pedantic && ./a.out
Segmentation fault
Cả gdb cũng không valgrind cung cấp bất kỳ thông tin hữu ích:
# 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
Vụ tai nạn không xảy ra khi tôi chuyển sang các tệp nhị phân 32 bit với cờ gcc -m32
. Nó không xảy ra hoặc nếu tôi sử dụng một sân chẵn (ví dụ: pitch = width * 2 + 2
). Bất cứ ai có thể giúp tôi để phát hiện các (chắc chắn là ngu ngốc) lỗi tôi thực hiện trong mã của tôi? Rất cám ơn trước!
UPDATE: Theo đề nghị của Jonathan, tôi vừa báo cáo vấn đề này để các nhà phát triển GCC: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56392
Tính toán độ cao của bạn trông không bình thường. Bạn có ý định đặt nó thành một giá trị lẻ n (tốt, một số lẻ của các phần tử uint16_t) không? Nó phổ biến hơn để xem nó được làm tròn đến bội số của 4 hoặc 8. – simonc
Có, nó được cố tình đặt thành một số lẻ. Vụ tai nạn không xảy ra với thậm chí cả sân ... và tôi không thể tìm ra lý do tại sao bởi bản thân mình :) – Tisys
So sánh mã lắp ráp đã tạo. Ngoài ra, bạn có thể muốn thử nghiệm với các tùy chọn riêng lẻ '-O3' bật để xem cái nào là thủ phạm (Xem http://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Optimize-Options. html # Tối ưu hóa-Tùy chọn cho một danh sách các tùy chọn). –