2015-05-02 23 views
19

Câu hỏi này nảy sinh trong bối cảnh của câu hỏi này: Find unexecuted lines of c++ codeMục loại xung đột cho các biến hệt định nghĩa

Khi tìm kiếm cho vấn đề này hầu hết mọi người đã cố gắng để thêm mã và các biến thành phần tương tự - nhưng điều này chắc chắn không phải là vấn đề đây. Dưới đây là một ví dụ làm việc tối thiểu:

unsigned cover() { return 0; } 

#define COV() do { static unsigned cov[2] __attribute__((section("cov"))) = { __LINE__, cover() }; } while(0) 

inline void foo() { 
     COV(); 
} 

int main(int argc, char* argv[]) 
{ 
     COV(); 

     if (argc > 1) 
       COV(); 

     if (argc > 2) 
       foo(); 

     return 0; 
} 

mà kết quả với g++ -std=c++11 test.cpp (g ++ (GCC) 4.9.2 20.150.212 (Red Hat 4.9.2-6)) trong các lỗi sau:

test.cpp:6:23: error: cov causes a section type conflict with cov 
    COV(); 
        ^
test.cpp:11:30: note: ‘cov’ was declared here 
     COV(); 
          ^

Các lỗi không phải là rất hữu ích mặc dù, vì nó không nêu lý do tại sao điều này được coi là một cuộc xung đột. Cả tệp .ii và .s tạm thời không đưa ra gợi ý nào về vấn đề có thể xảy ra. Trên thực tế, chỉ có một định nghĩa phần trong tệp .s

 .section  cov,"aw",@progbits 

và tôi không hiểu tại sao định nghĩa tiếp theo nên xung đột với điều này ("aw", @ progbits là chính xác ...).

Is there any way to get more information on this? See what the precise conflict is? Or is this just a bug...?

+0

Cũng thấy [Lỗi biên dịch "X gây xung đột loại phần với Y" nên cung cấp thêm thông tin] (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82209) trong Bộ theo dõi sự cố GCC. – jww

+4

Câu hỏi này là bản sao chính xác của [Dữ liệu tĩnh nội tuyến gây ra xung đột loại phần] (https: // stackoverflow.com/q/35091862/1362568), trong đó tôi đã viết câu trả lời được chấp nhận với giải thích chi tiết và [giải pháp sau đó của OP] (https://stackoverflow.com/a/36361512/1362568) là đẹp hơn. Việc sử dụng '__attribute__' như trong vấn đề không được GCC hỗ trợ. –

+0

@MikeKinghan gợi ý: 1/tạo bản tóm tắt câu trả lời xuất sắc của bạn từ bản sao. 2/kiếm tiền thưởng. 3/đóng câu hỏi là trùng lặp. – YSC

Trả lời

1

Thư thực sự rất tệ, nhưng không phải là lỗi. Vấn đề ở đây xảy ra với hàm nội tuyến foo() và xảy ra do các hàm nội tuyến phải được xác định trong mỗi ngữ cảnh dịch mà chúng được sử dụng. Trong số link chúng tôi có thể đọc về thuộc tính phần:
"..các biến được khởi tạo dự kiến ​​sẽ đi vào phần chung (hoặc bss) và có thể nhân với số 'được xác định'. làm cho trình liên kết phát ra lỗi nếu biến chưa được khởi tạo có nhiều định nghĩa ... ".

Do đó, khi hàm foo cần được 'xác định' trong hàm chính, trình liên kết tìm biến cov được xác định trước đó trong hàm nội tuyến foo và phát ra lỗi.

Hãy làm cho công việc xử lý trước và mở rộng COV() xác định để giúp làm sáng tỏ vấn đề:

inline void foo() 
{ 
    do { static unsigned cov[2] __attribute__((section("cov"))) = { 40, cover() }; } while(0); 
} 

int main(int argc, char *argv[]) { 
    do { static unsigned cov[2] __attribute__((section("cov"))) = { 44, cover() }; } while(0); 

    if (argc > 1) 
     do { static unsigned cov[2] __attribute__((section("cov"))) = { 47, cover() }; } while(0); 

    if (argc > 2) 
      foo(); 

Để tạo điều kiện lý luận, chúng ta hãy thay đổi các thuộc tính phần của định nghĩa trong chức năng foo inline để cov.2 chỉ để biên dịch mã. Bây giờ chúng ta không có lỗi, vì vậy chúng tôi có thể kiểm tra các đối tượng (.o) với objdump:

objdump -C -t -j cov ./cmake-build-debug/CMakeFiles/stkovf.dir/main.cpp.o 

./cmake-build-debug/CMakeFiles/stkovf.dir/main.cpp.o:  file format elf64-x86-64 

SYMBOL TABLE: 
0000000000000000 l d cov 0000000000000000 cov 
0000000000000000 l  O cov 0000000000000008 main::cov 
0000000000000008 l  O cov 0000000000000008 main::cov 

objdump -C -t -j cov.2 ./cmake-build-debug/CMakeFiles/stkovf.dir/main.cpp.o 

./cmake-build-debug/CMakeFiles/stkovf.dir/main.cpp.o:  file format elf64-x86-64 

SYMBOL TABLE: 
0000000000000000 l d cov.2 0000000000000000 cov.2 
0000000000000000 u  O cov.2 0000000000000008 foo()::cov 

Chúng ta có thể thấy trình biên dịch mà làm foo :: cov, trong phần cov.2 GLOBAL (có chữ ký của 'u' thư). Khi chúng tôi sử dụng cùng tên phần (cov), trình biên dịch, cố gắng ‘xác định’ foo trong khối chính gặp phải một cov được xác định toàn cầu trước đó và các vấn đề lỗi.

Nếu bạn thực hiện nội tuyến foo tĩnh (inline static void foo()..), Giúp trình biên dịch phát ra mã cho hàm nội tuyến và chỉ sao chép vào thời gian mở rộng, bạn sẽ thấy lỗi biến mất, vì không có foo chung :: cov.

+0

Tôi nghĩ đây là một sự phục hồi về câu trả lời của Mike trong câu hỏi được trích dẫn. Tuy nhiên, câu hỏi này là có liên quan với *** xác định *** các phần vấn đề. Đó là lý do tại sao: *** "Tiền thưởng này cố gắng để có được một câu trả lời chính xác để khắc phục sự cố xung đột bằng cách xác định chính xác những kẻ phạm tội" ***. (Chúng tôi có cùng một vấn đề. Chúng tôi có gần 200 tệp đối tượng và chúng tôi không biết biểu tượng nào đang gây ra lỗi. Không có cách nào thực tế chúng tôi có thể kiểm tra 10 nghìn biểu tượng từ hàng trăm tệp đối tượng theo cách thủ công) – jww

Các vấn đề liên quan