2013-02-20 35 views
13

Câu hỏi của tôi:Chức năng bình đẳng con trỏ trong C

  1. là chức năng bình đẳng con trỏ được bảo đảm theo tiêu chuẩn C?
  2. Nếu câu trả lời của (1) là có. Đó có phải là trường hợp bất kể con trỏ có được trong các đơn vị biên dịch cuối cùng khác nhau hay không (ví dụ: tệp thực thi chính và thư viện được chia sẻ)?
  3. Trình tải động xử lý như thế nào? (Tôi có thể suy nghĩ về một vài lý do mà điều này có thể phức tạp, tất cả liên quan đến mã PIC (ví dụ: các bảng GOT trong elf và bất kỳ COFF nào tương đương sử dụng cho điều đó)). Bất kể (1) và (2) trình tải linux dường như đảm bảo điều này.

Dưới đây là ví dụ. Các câu hỏi trên đun sôi cho dù C đảm bảo những gì main.c in: "Function equality: 1" hoặc "Function equality: 0" và, trong trường hợp đầu tiên, trình tải động làm cho điều đó xảy ra như thế nào.

common.h:

extern void * getc_main; 
extern void * getc_shared; 
void assign_getc_shared(); 

main.c:

#include <stdio.h> 
#include "common.h" 

int main() 
{ 
    getc_main = (void*) getc; 
    assign_getc_shared(); 
    printf("Function equality: %d\n", getc_main == getc_shared); 
    return 0; 
} 

shared.c:

#include <stdio.h> 
#include "common.h" 

void assign_getc_shared() 
{ 
    getc_shared = (void*) getc; 
} 

Trong Unix này sẽ được biên dịch với các lệnh sau:

cc -shared -fPIC -o libshared.so shared.c 
cc -o main main.c -L. -lshared 

Và thực hiện với:

LD_LIBRARY_PATH=. ./main 
+0

Đó là một cách khá dài để hỏi "là nó đảm bảo rằng các chức năng thư viện chuẩn chỉ được bao gồm một lần trong thực thi" –

+0

Và tôi nghĩ câu trả lời cho câu hỏi của ông Lister là "Không, nó không được bảo đảm" .Ví dụ: hàm có thể được gạch chân và nếu bạn lấy địa chỉ của hàm nội tuyến, hàm này sẽ được bao gồm dưới dạng hàm "thực" trong mã, có nghĩa là sẽ có nhiều chức năng cho cùng một hàm nguồn. –

+0

@MrLister Nếu tôi chỉ muốn biết điều đó, thì tôi sẽ chỉ hỏi điều đó. Lý do đặt câu hỏi phụ là vì tôi quan tâm đến việc biết chi tiết về cách trình tải động tương tác với vấn đề này. Từ bình luận của bạn tôi đoán bạn không, và đó là tốt. – fons

Trả lời

12

C 2011 (Ủy ban N1570 Dự thảo) 6.5.9 6: “Hai con trỏ so sánh bằng khi và chỉ khi ... cả hai đều là con trỏ đến cùng ... chức năng .... Vì vậy, có, hai con trỏ đến cùng một chức năng so sánh bằng nhau.

Khi địa chỉ của hàm được thực hiện trong hai mô-đun đối tượng khác nhau, trình biên dịch sẽ đặt một trình giữ chỗ trong mã đối tượng. Trình giữ chỗ đó được điền vào khi các mô-đun đối tượng được liên kết vào một tệp thực thi hoặc được liên kết với một thư viện động tại thời gian chạy. Đối với thư viện động, trình tải động điền vào tất cả trình giữ chỗ trong tệp thực thi khi cần hoặc địa chỉ của mỗi hàm thực sự là vị trí của một số mã sơ khai nhảy đến hàm thực tế và trình giữ chỗ trong hoặc được sử dụng bởi mã sơ khai được điền bởi trình tải động.

Ngoài ra, lưu ý rằng tệp thực thi có thể chứa nhiều hơn một thể hiện của hàm. Trình biên dịch có thể chèn hàm nội tuyến ở một vài nơi hoặc có thể, vì các lý do riêng của nó, bao gồm một chuyên môn hóa của hàm cũng như một phiên bản chung. Tuy nhiên, khi địa chỉ của hàm được thực hiện, trình biên dịch phải cung cấp địa chỉ của một phiên bản chung duy nhất. Ví dụ, nếu trình biên dịch có thể phát hiện chương trình không so sánh con trỏ, thì có thể, theo lý thuyết, có thể sử dụng một địa chỉ khác cho một số trường hợp của địa chỉ của chức năng.)

+0

Điều này có nghĩa là không thể triển khai trình biên dịch C tuân thủ C 2011 trên chế độ thực 80x86. Như bất kỳ điểm nào trong bộ nhớ có thể được truy cập thông qua 4096 khác nhau (xa/rất lớn) con trỏ. –

+4

@tristopia: Tôi không thấy kết luận của bạn như thế nào. Thực tế là mỗi địa chỉ có 4096 đại diện tiềm năng không ngăn cản trình biên dịch đảm bảo rằng các biểu diễn khác nhau của cùng một địa chỉ so sánh bằng nhau. Trình biên dịch không bắt buộc phải thực hiện 'a == b' với một lệnh đơn; nó là miễn phí để thực hiện số học để chuyển đổi mỗi 'a' và' b' từ bất kỳ định dạng nào chúng đang ở trong một địa chỉ duy nhất hoàn chỉnh và sau đó so sánh các địa chỉ đầy đủ kết quả. –

+3

Ngoài ra, trình biên dịch có quyền kiểm soát việc lấy địa chỉ, do đó, nó có thể đảm bảo rằng một đại diện cụ thể của một địa chỉ hàm được sử dụng và những người khác thì không. –

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