2011-04-05 44 views
39

Trong trường hợp nào GCC có thể không phải là gửi thông báo lỗi liên kết "tham chiếu không xác định" khi cố gọi các chức năng được thiết lập?GCC có thể không phàn nàn về các tài liệu tham khảo không xác định?

Ví dụ, một tình huống trong đó mã C này được biên dịch và liên kết bởi GCC:

void function() 
{ 
    made_up_function_name(); 
    return; 
} 

... mặc dù made_up_function_name là không có mặt bất cứ nơi nào trong mã (không tiêu đề, các file nguồn, khai báo, cũng không phải thư viện của bên thứ ba nào).

Loại mã đó có thể được GCC chấp nhận và biên soạn trong một số điều kiện nhất định mà không cần chạm vào mã thực? Nếu có, thì sao?

Cảm ơn.

CHỈNH SỬA: không có tuyên bố trước nào hoặc đề cập đến made_up_function_name có mặt ở bất kỳ nơi nào khác. Có nghĩa là grep -R của toàn bộ hệ thống tệp sẽ chỉ chỉ cho thấy dòng mã đơn chính xác.

+0

Có thể (miễn là bạn đang biên dịch C, không phải C++). Bạn đang cố gắng làm gì? –

+0

Tôi không cố gắng thực hiện bất cứ điều gì, nó đã xảy ra và tôi muốn biết tại sao nó có thể. Hàm made_up_function_name thực sự xuất hiện trong tệp nhị phân cuối cùng, được liên kết nếu tôi sử dụng "-g" và chỉnh sửa tệp bằng trình chỉnh sửa văn bản. – STenyaK

+1

Về lý do, hãy xem: http://stackoverflow.com/questions/4914589/c-prototype-functions/4914683, http://stackoverflow.com/questions/4800102/not-including-stdlib-h-does-not -produce-any-compiler-error/4800138 # 4800138, và có thể khá nhiều hơn nữa. –

Trả lời

68

Có, bạn có thể tránh báo cáo các tham chiếu chưa được xác định - sử dụng tùy chọn liên kết --unresolved-symbols.

g++ mm.cpp -Wl,--unresolved-symbols=ignore-in-object-files 

Từ man ld

--unresolved-ký tự = phương pháp

Xác định làm thế nào để xử lý những biểu tượng chưa được giải quyết. Có bốn giá trị có thể cho phương pháp:

 ignore-all 
      Do not report any unresolved symbols. 

     report-all 
      Report all unresolved symbols. This is the default. 

     ignore-in-object-files 
      Report unresolved symbols that are contained in shared 
      libraries, but ignore them if they come from regular object 
      files. 

     ignore-in-shared-libs 
      Report unresolved symbols that come from regular object 
      files, but ignore them if they come from shared libraries. This 
      can be useful when creating a dynamic binary and it is known 
      that all the shared libraries that it should be referencing 
      are included on the linker's command line. 

Các hành vi cho các thư viện chia sẻ trên của chính họ cũng có thể được điều khiển bởi tùy chọn - cho phép-shlib-không xác định [không-].

Thông thường, trình liên kết sẽ tạo thông báo lỗi cho mỗi báo cáo biểu tượng chưa được giải quyết nhưng tùy chọn - biểu tượng chưa được giải quyết có thể thay đổi điều này thành cảnh báo.

3

Nếu bạn khai báo nguyên mẫu của hàm trước khi sử dụng nó, nó sẽ biên dịch. Dù sao thì lỗi trong khi liên kết sẽ vẫn còn.

void made_up_function_name(); 
void function() 
{ 
    made_up_function_name(); 
    return; 
} 
+0

Câu hỏi đã chỉnh sửa để phản ánh điều này: hoàn toàn không có đề cập đến chức năng được tạo sẵn khác với đường gọi được hiển thị trong ví dụ. – STenyaK

1

Nếu không được gọi là function(), có thể không được bao gồm trong tệp thực thi và chức năng được gọi từ nó cũng không được tìm kiếm.

+0

để nó có thể biên dịch ngay cả khi không khai báo nguyên mẫu và sau đó được liên kết? Tôi nghĩ rằng ít nhất là nguyên mẫu nên được khai báo, nếu không nó sẽ tạo ra một lỗi phân tích cú pháp, phải không? – Heisenbug

+0

@ 0verbose - Tùy thuộc vào tiêu chuẩn C bạn sử dụng. Ban đầu, nguyên mẫu là không cần thiết. Và sau đó chỉ khi bạn có các kiểu tham số khác với int. –

0

Và sau đó có sự nastiness này với cờ -D được chuyển đến GCC.

$cat undefined.c 
void function() 
{ 
    made_up_function_name(); 
    return; 
} 


int main(){ 
} 

$gcc undefined.c -Dmade_up_function_name=atexit 
$ 

Chỉ cần hình dung tìm kiếm định nghĩa của made_up_function_name- nó xuất hiện ở đâu đó "hiện mọi thứ" trong mã. Tôi không thể nghĩ ra một lý do tốt để làm điều này trong mã.

Cờ -D là công cụ mạnh mẽ để thay đổi mã tại thời gian biên dịch.

+0

Cờ '-D' thay đổi mã tại thời gian * biên dịch *. Sau đó, có những thứ như '-Wl, - wrap' làm điều đó tại thời gian liên kết. –

+0

Và nếu một kết hợp '-D' với mã thông báo trước khi xử lý thì văn bản' make_up_function_name' không cần xuất hiện như vậy trong bất kỳ tệp makefile hoặc kịch bản lệnh xây dựng nào. –

2

TL; DRthể không phàn nàn, nhưng bạn không muốn điều đó. Mã của bạn sẽ bị lỗi nếu bạn buộc trình liên kết bỏ qua vấn đề. Nó sẽ phản tác dụng.

Mã của bạn dựa vào C cổ (trước C99) cho phép các hàm được khai báo hoàn toàn tại thời điểm sử dụng của chúng. mã của bạn là ngữ nghĩa tương đương để đoạn mã sau:

void function() 
{ 
    int made_up_function_name(...); // The implicit declaration 

    made_up_function_name(); // Call the function 
    return; 
} 

Các mối liên kết chính đáng phàn nàn rằng các tập tin đối tượng có chứa các biên soạn function() đề cập đến một biểu tượng mà không tìm thấy bất cứ nơi nào khác. Bạn phải sửa chữa nó bằng cách cung cấp việc triển khai cho made_up_function_name()hoặc bằng cách xóa cuộc gọi vô nghĩa. Đó là tất cả để có nó. Không có mối liên kết nào có liên quan.

0

Thuật toán "chuẩn" theo đó trình liên kết POSIX vận hành lá mở khả năng mã sẽ biên dịch và liên kết mà không có bất kỳ lỗi nào. Xem tại đây để biết chi tiết: https://stackoverflow.com/a/11894098/187690

Để khai thác khả năng tệp đối tượng có chứa function (hãy gọi nó là f.o) nên được đặt vào thư viện. Thư viện đó nên được đề cập trong dòng lệnh của trình biên dịch (và/hoặc linker), nhưng vào thời điểm đó không có tệp đối tượng nào khác (được đề cập trước đó trong dòng lệnh) nên thực hiện bất kỳ cuộc gọi nào đến function hoặc bất kỳ chức năng nào khác có trong f.o. Trong những trường hợp như vậy, người liên kết sẽ không thấy lý do nào để truy xuất f.o từ thư viện. Trình liên kết sẽ hoàn toàn bỏ qua f.o, hoàn toàn bỏ qua function và do đó, hoàn toàn không biết gì về lệnh gọi đến số made_up_function_name. Mã sẽ biên dịch mặc dù made_up_function_name không được định nghĩa ở bất kỳ đâu.

1

Khi bạn tạo cờ liên kết -r hoặc --relocatable, nó cũng sẽ không tạo ra bất kỳ thông báo lỗi liên kết "tham chiếu không xác định" nào.

Điều này là do -r sẽ liên kết các đối tượng khác nhau trong một tệp đối tượng mới được liên kết ở giai đoạn sau.

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