2010-11-11 42 views
12

Tôi muốn biết độ dài của hàm C (được viết bởi tôi) khi chạy. Bất kỳ phương pháp để có được nó? Có vẻ như sizeof không hoạt động ở đây.Cách lấy độ dài của hàm bằng byte?

+2

Hãy xác định "chiều dài của chức năng C" ** ** chính xác – pmg

+0

Tôi có nghĩa là bộ nhớ bị chiếm đóng bởi mã của hàm này. – Thomson

+1

Nếu bạn đang yêu cầu điều này vì lý do tương tự tôi đã tự hỏi về nó nhiều năm trước, hãy để tôi chỉ ra [Viết một Jit mới] (http://stackoverflow.com/questions/4097301/writing-a-new-jit) –

Trả lời

13

Không có cách nào trong tiêu chuẩn C để nhận được lượng bộ nhớ bị chiếm bởi một hàm.

0

Không có cách làm tiêu chuẩn nào trong C hoặc C++. Có thể tồn tại một cách tự nhiên các cách triển khai/nền tảng cụ thể để thực hiện nó, nhưng tôi không biết bất kỳ

3

Ví dụ: Codewarrior, bạn có thể đặt các nhãn xung quanh một hàm, ví dụ:

label1: 
void someFunc() 
{ 
    /* code goes here. */ 
} 
label2: 

và sau đó tính kích thước như (int)(label2-label1), nhưng điều này rõ ràng là rất phụ thuộc vào trình biên dịch. Tùy thuộc vào hệ thống và trình biên dịch của bạn, bạn có thể phải hack các tập lệnh liên kết, v.v.

+0

Không biết điều đó. Buồn cười. Sắp xếp. – haylem

+2

Có một [phần mở rộng GCC] tương tự (http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Labels-as-Values.html#Labels-as-Values), sử dụng nó có thể tính toán kích thước như '&& label2 - && label1' – Hasturkun

+0

Tôi hy vọng điều này sẽ làm việc, nhưng có vẻ như nó không thể làm việc trong Visual C++ (ngôn ngữ C). – Thomson

4

Thực thi (ít nhất là các tệp có thông tin gỡ lỗi) không lưu trữ độ dài của hàm theo bất kỳ cách nào. Vì vậy, không có khả năng phân tích cú pháp thông tin này trong thời gian chạy của bản thân. Nếu bạn phải thao tác với các hàm, bạn nên làm điều gì đó với các đối tượng của bạn trong việc liên kết giai đoạn hoặc bằng cách truy cập chúng dưới dạng các tệp từ tệp thực thi của bạn. Ví dụ: bạn có thể yêu cầu trình liên kết liên kết các bảng biểu tượng dưới dạng phần dữ liệu thông thường vào tệp thực thi, gán cho chúng một số tên và phân tích cú pháp khi chương trình chạy. Nhưng hãy nhớ, điều này sẽ được cụ thể cho mối liên kết và định dạng đối tượng của bạn.

Cũng lưu ý, rằng bố trí chức năng cũng là nền tảng cụ thể và có một số điều mà làm cho thuật ngữ "chức năng chiều dài" không rõ ràng:

  1. Chức năng có thể có cửa hàng sử dụng các hằng số trong các phần mã trực tiếp sau khi mã chức năng và truy cập chúng sử dụng địa chỉ liên quan đến PC (các trình biên dịch ARM làm điều này).
  2. Chức năng có thể có "prologs" và "epilogs" có thể có thể xảy ra với một số chức năng và do đó nằm bên ngoài cơ thể chính.
  3. Mã chức năng có thể nội dòng mã chức năng khác

Tất cả đều có thể đếm hoặc không tính theo độ dài chức năng.

Chức năng cũng có thể được biên dịch hoàn toàn bởi trình biên dịch, do đó, nó mất toàn thân.

+0

chúng có thể nhưng các chức năng này vẫn có độ dài cố định, chúng sẽ chỉ hoạt động sai mà không có các phụ thuộc bên ngoài đó. Các hàm này có thể được xây dựng lại để được tự chứa bằng cách lấy các phụ thuộc của chúng làm các đối số và nhiều hàm, đặc biệt là các hàm gọi lại, là chính xác điều này. – Dmitry

1

Không có cơ sở nào được xác định trong chính ngôn ngữ C để trả về độ dài của hàm; chỉ đơn giản là có quá nhiều biến liên quan (trình biên dịch, tập lệnh đích, tệp đối tượng/định dạng tệp thực thi, cài đặt tối ưu, cài đặt gỡ lỗi, v.v.). Mã nguồn rất giống nhau có thể dẫn đến các chức năng có kích thước khác nhau cho các hệ thống khác nhau.

C đơn giản không cung cấp bất kỳ loại khả năng phản chiếu nào để hỗ trợ loại thông tin này (mặc dù các trình biên dịch riêng lẻ có thể cung cấp các phần mở rộng, chẳng hạn như ví dụ Codewarrior được trích dẫn bởi sskuce). Nếu bạn cần biết có bao nhiêu byte mà hàm của bạn chiếm trong bộ nhớ, thì bạn sẽ phải kiểm tra trực tiếp đối tượng được tạo ra hoặc tệp thực thi.

sizeof func sẽ không hoạt động vì biểu thức func đang được coi là con trỏ đến hàm, do đó bạn sẽ nhận được kích thước của giá trị con trỏ chứ không phải chính hàm đó.

+0

Trong trình biên dịch phù hợp, 'sizeof func' không hoạt động vì một hàm thiết kế hàm không phải là toán hạng hợp lệ của toán tử' sizeof'. – caf

+0

@caf: * facepalm * Vâng, bạn nói đúng. Tôi biết rằng. Có thật không. –

+0

@JohnBode trong khi bạn nói đúng rằng thông tin này không phải là di động; trình biên dịch vẫn còn nhận thức rõ về tất cả các yếu tố này tại thời gian biên dịch, và kết quả tạo ra cảm giác hoàn hảo cho nền tảng cụ thể đó. Việc biết kích thước của một hàm có ý nghĩa trên nền tảng đó bởi vì nó cho phép bạn ghi nhớ mã shell của các hàm "chỉ đọc", có các hàm ý rất thú vị và nhất quán mà chúng ta không thể nghiên cứu mà không có một tính năng như vậy. – Dmitry

3

Bắt đầu của hàm là con trỏ hàm, bạn đã biết điều đó.

Vấn đề là tìm Cuối cùng, nhưng điều đó có thể được thực hiện theo cách này:

#include <time.h> 

int foo(void) 
{ 
    int i = 0; 
    ++i + time(0); // time(0) is to prevent optimizer from just doing: return 1; 
    return i; 
} 

int main(int argc, char *argv[]) 
{ 
    return (int)((long)main - (long)foo); 
} 

Nó hoạt động ở đây vì chương trình chỉ có hai chức năng vì vậy nếu mã được tái ra lệnh (chính thực hiện trước khi foo) thì bạn sẽ nhận được một phép tính không liên quan (tiêu cực), cho bạn biết rằng nó không hoạt động theo cách này, nhưng nó sẽ làm việc nếu bạn di chuyển mã foo() vào main() - chỉ cần trừ đi kích thước chính() mà bạn nhận được trả lời tiêu cực ban đầu.

Nếu kết quả là dương, thì sẽ đúng - nếu không có đệm được thực hiện (có, một số trình biên dịch vui vẻ thổi phồng mã, hoặc để căn chỉnh hoặc cho các lý do khác rõ ràng).

Đoạn kết thúc (int) (dài) là dành cho tính di động giữa mã 32 bit và 64 bit (con trỏ hàm sẽ dài hơn trên nền tảng 64 bit).

Đây là thiết bị di động hàng ngày và hoạt động tốt.

12

Có cách xác định kích thước của hàm. Lệnh này là:

nm -S <object_file_name> 

Điều này sẽ trả về kích thước của từng hàm bên trong tệp đối tượng. Tham khảo các trang hướng dẫn sử dụng trong GNU bằng cách sử dụng 'man nm' để thu thập thêm thông tin về điều này.

+0

hoặc objdump, FWIW. – sehe

+0

'nm -S --size-sort -t d | grep 'hiển thị kích thước trong cơ sở 10 (' -t d' cho * thập phân *) của các biểu tượng có chứa 'mẫu' trong tên của chúng, được sắp xếp theo kích thước. Tuyệt đấy. – hdl

12

Bạn có thể lấy thông tin này từ trình liên kết nếu bạn đang sử dụng tập lệnh trình liên kết tùy chỉnh. Thêm phần liên kết chỉ dành cho hàm đã cho, với các ký hiệu liên kết ở hai bên:

Sau đó, bạn có thể chỉ định cụ thể chức năng cho phần đó. Sự khác biệt giữa các ký hiệu là độ dài của hàm:

#include <stdio.h> 

int i; 

__attribute__((noinline, section(".mysection"))) void test_func (void) 
{ 
    i++; 
} 

int main (void) 
{ 
    extern unsigned char mysec_start[]; 
    extern unsigned char mysec_end[]; 

    printf ("Func len: %lu\n", mysec_end - mysec_start); 
    test_func(); 

    return 0; 
} 

Ví dụ này dành cho GCC, nhưng bất kỳ công cụ C nào đều phải có cách xác định phần nào để gán hàm. Tôi sẽ kiểm tra kết quả chống lại danh sách lắp ráp để xác minh rằng nó hoạt động theo cách bạn muốn.

+0

Bạn có thể thực hiện việc này mà không cần tập lệnh trình liên kết tùy chỉnh bằng cách gọi phần bằng tên định danh C hợp lệ, ví dụ 'mysection' thay vì' .mysection' và sử dụng '__start_mysection' và' __stop_mysection' thay vì 'mysec_start' và' mysec_end '. Trình liên kết tự động xác định các biểu tượng này cho mỗi phần gặp phải. – Janiels

-3

Bạn có thể tìm chiều dài của hàm C bằng cách trừ các địa chỉ của hàm. Để tôi cung cấp cho bạn một ví dụ

int function1() 
    { 
    } 

int function2() 
{ 
    int a,b; //just defining some variable for increasing the memory size 
    printf("This function would take more memory than earlier function i.e function01 "); 
} 

int main() 
{ 
    printf("Printing the address of function01 %p\n",function01); 
    printf("Printing the address of function02 %p\n",function02); 
    printf("Printing the address of main %p\n",main); 
    return 0; 
} 

Hy vọng bạn sẽ nhận được câu trả lời sau khi biên dịch. Sau khi biên dịch, bạn sẽ có thể thấy sự khác biệt về kích thước của hàm01 và hàm2.

Lưu ý: Thông thường có 16byte khác nhau giữa một hàm và một hàm khác.

+0

ví dụ của bạn không chứng minh bất cứ điều gì :) bạn chỉ cần in các địa chỉ hàm! –

1

Chỉ cần trừ địa chỉ của hàm của bạn khỏi địa chỉ của hàm tiếp theo. Nhưng lưu ý nó có thể không hoạt động trên hệ thống của bạn, vì vậy sử dụng nó chỉ nếu bạn là chắc chắn 100%:

#include <stdint.h> 

int function() { 
    return 0; 
} 

int function_end() { 
    return 0; 
} 

int main(void) { 
    intptr_t size = (intptr_t) function_end - (intptr_t) function; 
} 
Các vấn đề liên quan