2013-03-05 50 views
7

Tôi đang biên dịch mã nguồn của mình trên 2 máy khác nhau sử dụng các phiên bản khác nhau của gcc.biên dịch mã nguồn trên 2 phiên bản khác nhau của gcc

CFLAGS C89

-Wall -Wextra -Wunreachable-code -g -m32 -D_DEBUG -O0 -D_LARGEFILE64_SOURCE -D_REETRANT -D_THREAD_SAFE 

Một là redhat-4

gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-46) 
Linux 203_test_server 2.6.18-164.el5 #1 SMP Tue Aug 18 15:51:48 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux 

Và ai là Fedora 18

gcc (GCC) 4.7.2 20121109 (Red Hat 4.7.2-8) 
Linux localhost.localdomain 3.8.1-201.fc18.x86_64 #1 SMP Thu Feb 28 19:23:08 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux 

fedora My 18 biên dịch không có lỗi. Tuy nhiên, trên máy redhat 4 tôi nhận được một số lỗi.

channel.h:35: error: redefinition of typedef ‘channel_t’ 
internal.h:19: error: previous declaration of ‘channel_t’ was here 

Tôi nghĩ rằng lỗi này chỉ là vấn đề vòng tròn. Tuy nhiên, với cùng một cơ sở mã sẽ biên dịch trên 2 máy khác nhau thực sự tạo sự khác biệt bằng cách sử dụng 2 phiên bản gcc khác nhau?

Tôi đã nghĩ rằng việc sử dụng phiên bản trình biên dịch mới hơn sẽ tạo ra nhiều lỗi hơn, vì trình biên dịch mới hơn có thể nghiêm ngặt hơn.

Đây không phải là câu hỏi để giải quyết lỗi, nhưng là câu hỏi chung về trình biên dịch.

Có lá cờ nào tôi có thể đặt để tránh điều này trong tương lai hay không. Có lẽ nếu biên dịch trên phiên bản này của gcc làm điều này, nếu các phiên bản không tương thích?

+1

Có, các trình biên dịch/phiên bản/cờ khác nhau có thể tạo ra các kết quả khác nhau, đặc biệt. trong '# ifdef'-mã nặng. –

+0

theo như 'bất kỳ cờ nào tôi có thể đặt để tránh điều này trong tương lai', câu trả lời của tôi có bao gồm điều đó hay bạn đang nghĩ đến điều gì đó khác? – Mike

+0

một số thông tin hữu ích sẽ tốt đẹp, nó có nhiều khả năng là một tiêu đề kèm theo khác nhau trên một hệ thống hơn trình biên dịch, nhưng bạn không bao giờ đề cập đến nơi channel.h hoặc internal.h là hoặc cách chúng được đưa vào. các đường xung quanh xung quanh nơi channel_t xuất hiện sẽ hữu ích quá ... ít nhất là đến ifdefs. CFLAG của bạn định nghĩa có nghĩa là hoàn toàn không có gì mà không có điều đó. – technosaurus

Trả lời

4

Đó là một bản sao của: Why "Redefinition of typedef" error with GCC 4.3 but not GCC 4.6?

Câu trả lời là gcc được thay đổi để điều chỉnh việc kiểm tra này.

http://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=ce3765bf44e49ef0568a1ad4a0b7f807591d6412

Đôi khi, cảnh báo cho hành vi quy định tại các ngôn ngữ, nhưng được coi là xấu thực tế, được coi là quá khắt khe vì một số trường hợp sử dụng hữu ích và/hoặc vô hại có trong cảnh báo. Các nhà phát triển trình biên dịch sau đó cố gắng sửa chữa theo cách ngược lại, tức là giảm số lượng cảnh báo. Trong trường hợp này, thay đổi làm cho cảnh báo chỉ xuất hiện khi định nghĩa thứ hai thay đổi typedef thành một kiểu khác, nhưng tương thích.

Ví dụ hiện tại khác là -Wshadow in gcc 4.8 vừa được công bố. Trong lưu ý phát hành, nó nói rằng -Wadow sẽ không cảnh báo nữa nếu một tên chức năng bị bóng khác.

Xem: http://gcc.gnu.org/gcc-4.8/changes.html

Chỉnh sửa: làm thế nào bạn có thể tránh điều này: hoặc xóa một trong những định nghĩa, hoặc di chuyển nó đến một riêng biệt bao gồm tập tin và xóa cả các định nghĩa khác.

10

Nó sẽ phụ thuộc vào tiêu đề nào được bao gồm bởi mã nguồn. Nếu bạn đang liên kết với các thư viện bên ngoài, có thể mã nguồn của bạn không tương thích với phiên bản của thư viện được cài đặt trên hệ thống cũ hơn.

Nếu mã nguồn không bao gồm bất kỳ tiêu đề thư viện bên ngoài nào (ngoại trừ thư viện C) thì có thể có các chỉ thị tiền xử lý cần thay đổi.

EDIT:

Sau khi tìm kiếm Google, dường như channel_t là từ một tiêu đề hạt nhân. Bạn đang sử dụng hạt nhân phát hành xa nhau trên hai máy. Nếu mã phụ thuộc vào tệp tiêu đề hạt nhân, nó có thể yêu cầu phiên bản hạt nhân mới hơn so với máy Red Hat. Bạn chưa chỉ định mã là gì (nó là trình điều khiển thiết bị?) Hay tệp nào bao gồm, vì vậy rất khó để nói thêm.

+0

Bạn trả lời rất hay, vì vậy +1 cung cấp cho bạn một thẻ 'đẹp' .. –

+0

@GrijeshChauhan: cảm ơn bạn! – teppic

4

So sánh nội dung của kênh.h và internal.h trên hai hệ thống mà bạn đang nhận được các kết quả khác nhau. Tôi nghi ngờ vấn đề là phiên bản của gcc. Có nhiều khả năng là các lỗi là kết quả của việc thay đổi mã cho các tệp đó theo thời gian, như khi một hệ thống có phiên bản thư viện mới hơn và tệp tiêu đề được liên kết hơn tệp kia.

1

Để bắt đầu, hãy nói về vấn đề của bạn một chút. Tôi nghĩ nguyên nhân có khả năng nhất gây ra lỗi hệ thống của bạn trên một hệ thống so với hệ thống khác là mã không giống nhau; bạn có thể muốn xác minh điều này thông qua một số công cụ hoặc lệnh diff để tìm kiếm bất kỳ thay đổi tinh tế nào đã xuất hiện trong cơ sở mã của bạn. vấn đề thường khi tôi đã nhìn thấy với kiểu lỗi, bạn có cái gì đó như:

typedef struct Foo* Fooptr; 

Trong một tập tin tiêu đề và sau đó:

typedef struct Foo 
{ 
    int bar; 
} *Fooptr; 

trong file nguồn. Có nghĩa là bạn có thể chỉ cần gõ typedef vào nguồn và nó sẽ là OK. Chỉ cần một cái gì đó để tìm kiếm.

Bây giờ nếu nó một vấn đề gcc, một lựa chọn thứ hai để giải quyết vấn đề của bạn, nó có thể have multiple versions of gcc on the same computer và sau đó để xác định chính xác phiên bản của gcc để chạy với qua tùy chọn -v. Vì vậy, có thể là một ý tưởng hay khi cho 4.1.2 một shot trên máy Fedora 18 của bạn.

lưu ý khác, nếu bạn sử dụng tùy chọn -v, nhưng không định một phiên bản của gcc để chạy, bạn sẽ nhận được (trên đầu ra stderr) các lệnh thực thi để chạy các giai đoạn biên dịch. Điều này có thể hữu ích để xem điều gì đang xảy ra và nếu có bất kỳ sự khác biệt lớn nào giữa những gì đang xảy ra trên mỗi máy.


OK, bây giờ cho câu hỏi của bạn. Có, có các cờ để biên dịch trên “phiên bản X” của gcc: Để bắt đầu có __VERSION__ Predefined Macro, điều này sẽ nhổ lại cho bạn số const char * của số phiên bản. Điều này có thể khá hữu ích, nhưng như các tài liệu hướng dẫn gcc khẳng định:

Bạn không nên dựa vào nội dung của nó có bất kỳ hình thức cụ thể, nhưng nó có thể được tính trên để chứa ít nhất số lượng phát hành

Mặc dù vậy, tôi thường chỉ nhìn thấy 1 hình thức đầu ra từ cái này giống như "4.6.3" nếu phiên bản gcc của tôi là 4.6.3-1ubuntu5.

Bây giờ nếu bạn biết (hoặc nghi ngờ) rằng một số mã của bạn sẽ gây ra một phiên bản đặc biệt của gcc để gây ra lỗi, bạn có thể sử dụng __GNUC__, __GNUC_MINOR__, và __GNUC_PATCHLEVEL__ macro được xác định trước để "bảo vệ" bản thân:
Dưới đây là một ngắn gọn-nó hiển thị ở mức cao nhất làm thế nào để sử dụng nó:

#if __GNC__ == 3 
    printf(“Hello version 3.x.x\n”); 
#elif __GNC__ == 4 
    printf(“Hello version 4.x.x\n”); 
#endif 

Vì vậy, trên hệ thống ở trên mà phiên bản 4.6.3 bạn sẽ thấy thông báo “Hello version 4.xx”. Sau đó, bạn có thể được nâng cao hơn và kiểm tra subversions cũng như:

#if __GNUC__ > 3 || \ 
    (__GNUC__ == 3 && (__GNUC_MINOR__ > 2 || \ 
     (__GNUC_MINOR__ == 2 && \ 
      __GNUC_PATCHLEVEL__ > 0)) 
    printf(“I’m a gcc greater than 3.2.0\n”); 
#endif 

Hoặc phiên bản sạch của rằng việc sử dụng vĩ mô của riêng bạn:

#define GCC_VERSION (__GNUC__ * 10000 \ 
    + __GNUC_MINOR__ * 100 \ 
    + __GNUC_PATCHLEVEL__) 
#if GCC_VERSION > 30200 
    printf(“I’m a gcc greater than 3.2.0\n”); 
#endif 

Để giải quyết câu hỏi của bạn về nếu phiên bản khác nhau của gcc sẽ tạo ra các lỗi khác nhau, bạn chính xác rằng trong mỗi bản phát hành gcc sẽ xảy ra nhiều hơn và đôi khi mọi thứ thay đổi, do đó bạn sẽ thấy sự khác biệt giữa các phiên bản khác nhau của trình biên dịch. Đặt cược tốt nhất là kiểm tra ghi chú phát hành cho mỗi phiên bản giữa hai phiên bản bạn đang sử dụng. (từ 4.1 đến 4.7).

Tôi không chắc chắn bạn có kiến ​​trúc đích nào, vì vậy hãy đảm bảo rằng bạn kiểm tra các phần cụ thể đó trong từng tài liệu. Nhưng tôi nghĩ bạn thực sự muốn có một cái nhìn tại "Build system improvements""Incompatible changes to the build system", họ cũng tạo một phần cụ thể cho mã C có thể hữu ích để xem xét.

1

Không có đủ thông tin ở đây để nói chính xác những gì đang xảy ra. Tôi tham gia với những người nói rằng nó không phải là một vấn đề phiên bản trình biên dịch.

Lỗi này xảy ra (rõ ràng) khi trình biên dịch gặp hai khai báo khác nhau cho cùng một tên. Nó không quá khó để tìm ra lý do tại sao điều này xảy ra.

Kiểm tra tệp makefile để tìm các tệp tiêu đề internal.hchannel.h đang được tham chiếu. Các dòng được trích dẫn sẽ có số typedef hoặc các khai báo khác cho channel_t tại đó. Làm việc ra ngoài từ những tờ khai này để tìm manh mối.

Tôi phải giả định rằng một hoặc cả hai tệp này nằm trong các thư viện bạn đang sử dụng. Nếu cả hai internal.hchannel.h là mã của riêng bạn, hãy gỡ lỗi mã của riêng bạn!

Nếu không có nhiều khả năng. Các khả năng nhất là

  1. Preprocessor -D hoặc #define cờ ed là không chính xác để nhiều tờ khai đang được điều kiện biên soạn khi chỉ có một nên.

  2. Hai thư viện khác hoặc tiêu đề chuẩn khác và thư viện có xung đột tên.

  3. Mã của riêng bạn có xung đột với thư viện hoặc tiêu đề chuẩn. Nếu channel_t là loại bạn đã xác định, đó là một vấn đề. Bạn không nên xác định các loại của riêng bạn kết thúc bằng _t vì chúng được dành riêng cho việc triển khai.

Số 1 ở trên có thể xảy ra theo nhiều cách, nhưng phổ biến nhất là cấu hình sai thư viện. Thư viện thường phải là ./configure được chỉnh sửa cho hệ điều hành mà chúng đang được sử dụng. Nếu bạn cấu hình trong một Linux và sao chép sang một Linux khác, bạn đang yêu cầu các vấn đề như bạn đang thấy.

Số 2 có thể xảy ra trên một linux và không phải do sự khác biệt phiên bản thư viện. Trong trường hợp này, hãy cập nhật máy bằng lỗi với cùng phiên bản với phiên bản không có lỗi. Đừng quên chạy ./configure.

Đối với số 3 sửa chữa là hiển nhiên. Thay đổi tên loại của bạn.

Tôi thấy channel.hchannel_t ở Tor.Dự đoán hoang dã của tôi là bạn đang sử dụng Tor và xem xét cấu hình sai Tor trên máy với lỗi.

1

Đây không phải là câu hỏi để giải quyết lỗi, nhưng là câu hỏi chung về trình biên dịch.

Có lá cờ nào tôi có thể đặt để tránh điều này trong tương lai không.

Mỗi phiên bản cụ thể của trình biên dịch sẽ có công tắc hoặc cờ riêng.

Nếu phiên bản trình biên dịch được tạo để chấp nhận một số chuyển mạch nhất định và một trong số đó là một trong những điều bạn cần để tránh kiểm tra một số mã nguồn của bạn thì có/sẽ là cách để tránh nó trong tương lai.

Nếu phiên bản trình biên dịch, phiên bản gần đây hoặc tương lai, bạn đang sử dụng không có/chấp nhận chuyển đổi để tránh/bỏ qua một số kiểm tra trên mã nguồn của bạn thì không có cách nào để tránh nó.

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