C cho biết đó là hành vi không xác định.
(C99, 6.9p5) "Nếu số nhận dạng được khai báo với liên kết bên ngoài được sử dụng trong biểu thức (không phải là một phần của toán hạng sizeof mà kết quả là hằng số nguyên), ở đâu đó trong toàn bộ chương trình sẽ có chính xác một định nghĩa bên ngoài cho số nhận dạng, nếu không, sẽ không có nhiều hơn một "
Là hành vi không xác định có nghĩa là trình liên kết có thể hủy bỏ quy trình liên kết trong sự hiện diện của nhiều định nghĩa đối tượng bên ngoài.
Liên kết bây giờ đẹp (hoặc ác, bạn có thể chọn) và thường có tiện ích mở rộng mặc định để xử lý nhiều định nghĩa đối tượng bên ngoài và không bị lỗi trong một số trường hợp.
Nếu bạn đang sử dụng gcc
và ld
từ binutils, bạn sẽ gặp lỗi nếu hai đối tượng của bạn được khởi tạo rõ ràng. Ví dụ: bạn có int x = 0;
trong đơn vị dịch đầu tiên và double x = 0.0;
.
Nếu không, nếu một trong các đối tượng bên ngoài không được khởi tạo rõ ràng (tình huống trong ví dụ của bạn) gcc
sẽ âm thầm kết hợp hai đối tượng thành một biểu tượng. Bạn vẫn có thể yêu cầu người liên kết báo cáo cảnh báo bằng cách chuyển cho nó tùy chọn --warn-common
.
Ví dụ khi liên kết các module:
gcc -Wl,--warn-common module1.o module2.o
Để quá trình liên kết hủy bỏ, bạn có thể yêu cầu các mối liên kết để điều trị tất cả các cảnh báo là lỗi sử dụng --fatal-warnings
tùy chọn (-Wl,--fatal-warnings,--warn-common
).
Một cách khác để hủy quá trình liên kết là sử dụng tùy chọn trình biên dịch -fno-common
, như được giải thích bởi @teppic trong câu trả lời của anh ấy. -fno-common
cấm các đối tượng bên ngoài nhận loại biểu tượng chung khi biên dịch. Nếu bạn làm điều đó cho cả hai mô-đun và sau đó liên kết, bạn cũng sẽ nhận được lỗi liên kết nhiều định nghĩa.
gcc -Wall -fno-common -c module1.c module2.c
gcc module1.o module2.o
Vì vậy, trong trường hợp này chỉ có một 'x' trong bảng biểu tượng? Tôi có thể thấy một số lỗi lạ phát sinh từ đó. Thx – amorimluc
@amorimluc trong trường hợp của bạn cơ hội bạn sẽ thích nhận được một lỗi từ linker hoặc một đối tượng duy nhất trong nhị phân cuối cùng và chương trình của bạn sẽ gọi hành vi không xác định. – ouah
Tôi nghĩ rằng tôi sẽ, nhưng nó biên dịch và liên kết tốt. Và x được in dưới dạng int nhưng với mẫu bit của float 3.14. Điều này có thể không xảy ra nhiều trong cuộc sống thực, nhưng chắc chắn sẽ khó tìm ra lỗi tinh vi này trong một chương trình lớn ... – amorimluc