2014-06-11 22 views
6

Giả sử tôi có hai file nguồn - UndefErr.cpp:Có cách nào bỏ qua các tham chiếu chưa được xác định không được sử dụng không?

#include <cstdio> 

void UndefFunc(); 
void Func2(){UndefFunc();} 

void Func1(){printf("Hi\n");} 

main.cpp:

void Func1(); 

int main(){ 
    Func1(); 
    return 0; 
} 

Như bạn thấy trong UndefErr.cpp các Func2() đi để kích hoạt lỗi, cho nó bằng cách sử dụng không xác định UndefFunc(). Tuy nhiên, chức năng chính không quan tâm đến số Func2()! Theo số a relevant question Tôi có thể chuyển một tùy chọn - biểu tượng không được giải quyết = bỏ qua-trong-đối tượng-tệp cho trình liên kết, nhưng tôi muốn có một điều khác biệt. Tôi cần một mối liên kết để biết nếu các chức năng không xác định được sử dụng ở đâu đó, và chỉ sau đó thất bại.

Lý do đặt câu hỏi lạ như vậy là tôi đang cố gắng sử dụng lwIP và khó hiểu tất cả các phụ thuộc của nó (Tôi chỉ cần TCP/IP) và tôi không thể tìm thấy hướng dẫn trên internet. Vì vậy, tôi nghĩ rằng tôi có thể biên dịch hầu hết các tệp (hoặc tất cả) .c và viết một số thử nghiệm đơn giản để xem nó hoạt động như thế nào. Nhưng cách tiếp cận này tình cờ gặp "các tham chiếu không xác định", hầu hết trong số chúng có thể không liên quan đến hệ thống usecase.

+0

có vẻ như liên kết có thể chỉ "tìm ra" nếu tham chiếu thậm chí cần được giải quyết ... một giải pháp mặc dù là nếu không có nhiều chức năng để làm cho nó cồng kềnh bạn chỉ có thể khai thác chúng trong chính. cpp ... ví dụ 'void UndefFunc() {}' – mark

+0

@mark không, trong dự án có rất nhiều chức năng. Và vấn đề chính mà tôi không biết, mà các chức năng không được sử dụng, đó là lý do tại sao tôi muốn bằng cách nào đó để tự động hóa nó .. –

+0

Tôi không hiểu câu hỏi. Trình liên kết sẽ khiếu nại nếu nó gặp một hàm không xác định. –

Trả lời

4

với GCC 4.8.2 Tôi quản lý để liên kết mã không có lỗi như sau:

$ g++ -c main.cpp -O3 -flto 
$ g++ -c UndefErr.cpp -O3 -flto 
$ g++ main.o UndefErr.o -flto -O3 -o out 

Tôi biết -flto sẽ tạo một hành vi mối liên kết như thể -fwhole-program đã được thông qua và toàn bộ điều là một đơn vị biên dịch đơn . Và -fwhole-program, theo hướng dẫn, tương ứng với cách sử dụng thích hợp static về chức năng, vì vậy cho phép chức năng không được sử dụng được loại bỏ khỏi đầu ra (tức là bạn đảm bảo trình biên dịch tất cả các chức năng của bạn sẽ không được sử dụng bởi một số mã khác và điểm duy nhất bạn đảm bảo cho người dùng của mình là main()).

Tôi phải thêm -O3, tôi không chắc chắn tại sao chính xác, nhưng trình biên dịch không quan tâm đến việc kiểm tra các chức năng và loại bỏ mã chết mà không có nó.

+0

Tuyệt vời, tôi không bao giờ biết tùy chọn này! Và có, nếu không có '-O3' được thông qua trong thời gian biên dịch, mối liên kết vì lý do nào đó từ chối hủy bỏ các chức năng không sử dụng. –

+1

Với MSYS2 xây dựng của MinGW GCC 5.3.0 tôi đã có thể đạt được loại bỏ các chức năng không sử dụng và do đó tránh lỗi "không xác định tham chiếu" cho các biểu tượng những chức năng tham chiếu với các tùy chọn trình biên dịch '-flto -Og' –

3

Sự cố là chức năng chưa xác định của bạn là sử dụng. Mã đối tượng cho Func2 đã được tạo, có một tham chiếu đến chưa tồn tại UndefFunc và mã này được chuyển đến trình liên kết. Trình biên dịch không có cách nào để hiểu rằng hàm này sẽ luôn không được xác định vì có nhiều đơn vị dịch.

Cách duy nhất để tránh lỗi biên dịch là yêu cầu trình liên kết mà bạn không cần mã đối tượng cho các chức năng không sử dụng, để nó không cố gắng tạo assembly cho trường hợp này.

+1

Tôi đã tìm kiếm xung quanh, và tôi chỉ thấy rằng có lẽ tôi cần hai thứ: sử dụng '-fdata-sections -ffunction-sections' làm cờ để mỗi chức năng nằm trong phần riêng của nó (để cho phép một trình liên kết đến xem một tham chiếu giữa các phần), và sau đó trình liên kết cần biết hàm chính xác (* chính * trong trường hợp của tôi), từ đó cần theo dõi một tham chiếu. Tôi cũng chỉ thấy rằng * LD * có một ngôn ngữ kịch bản, vì vậy có lẽ ở đây tôi đi - có vẻ như, rằng không có một cách tiêu chuẩn để làm những gì tôi muốn. –

+0

Tôi nghĩ nó đáng nói đến, trong kịch bản trên tôi nên theo dõi từ hàm '_start', vì nó là hàm đầu tiên được thực hiện. Khác tôi có thể kết thúc với một tập tin thực thi bị hỏng. –

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