2015-11-13 19 views
6

Tôi đang viết một hàm được gọi là ở cuối chuỗi đệ quy. Hàm này cần tìm ra vị trí của nó trong bộ nhớ tại thời điểm nó được gọi. Mã như sau:Con trỏ trỏ đến chính nó C

void recover() 
{ 
    int * x = (int *)&x; 
} 

Vấn đề là chương trình chỉ bỏ qua tuyên bố này như thể nó chưa bao giờ được viết. Tôi đã xác minh điều này trong GDP. Bạn có thể nghĩ ra bất kỳ lý do nào tại sao dòng này bị bỏ qua không?

Cảm ơn!

+6

Bạn mong đợi tuyên bố này sẽ làm gì? Như được viết, hàm không làm gì cả, và đây là những gì bạn thấy. Bất kỳ trình biên dịch nửa phong nha sẽ tối ưu hóa toàn bộ chức năng này đi. –

+0

'printf (" Chức năng tại địa chỉ: 0x% x \ n ", phục hồi);' – karlphillip

+0

Tôi cũng cần địa chỉ bộ nhớ này để tôi có thể truy cập vào GDP và sử dụng hiệu quả để quay ngược lại các cuộc gọi hàm trước đó.Mục tiêu cuối cùng của tôi là tìm các đối số ban đầu được chuyển vào hàm foo, trong đó recovery() được gọi là – prestige13

Trả lời

6

Nếu bạn đang biên dịch với tối ưu hóa được bật, thì mã này có thể được tối ưu hóa do không có hiệu lực trên chương trình. Sử dụng tùy chọn -O0.

+0

Điều này làm việc, cảm ơn bạn! – prestige13

8

Khai báo biến là volatile. Nó sẽ ngăn chặn tối ưu hóa trình biên dịch.

volatile int * x = (int *)&x; 
+0

Điều này làm việc, cảm ơn bạn! – prestige13

4

Mã bạn viết có lẽ là hành vi không xác định vì bạn đang đúc một con trỏ đến một con trỏ đến một int đến một con trỏ một int.

Một con trỏ không thể tự mình trỏ đến một cách khái niệm vì bạn sẽ không bao giờ có thể đạt được cấp độ vô hướng phù hợp. Dưới đây là lý do:

Declaration  | Type  | Type after using the & operator 
-------------------------------------------------------------- 
int x;   | int  | &x is an (int*) 
int* x;   | int * | &x is an (int**) 
int** x;   | int ** | &x is an (int***) 

Tuy nhiên, một void* là loại duy nhất của con trỏ tôi có thể nghĩ rằng có thể được phép phá vỡ quy tắc này, nhưng tôi không chắc chắn nếu nó sẽ là hợp pháp theo tiêu chuẩn.

tôi sẽ đề nghị bạn viết như sau thay vì những gì bạn có:

int* recover() 
{ 
    int local = 0; 
    return &local; 
} 

Và biên dịch nó không có tối ưu hóa như @ysap gợi ý.

Vẫn còn trong ví dụ của bạn, có vẻ như bạn đang cố gắng tìm ra vị trí trên cùng của ngăn xếp và điều đó rất dễ thực hiện khi lắp ráp. Tất cả những gì bạn cần làm là đọc con trỏ ngăn xếp. Tuy nhiên, điều này không phải là quá sạch sẽ tiếp xúc trong C. Mặc dù GCC không có một số helper functions cho nhiệm vụ tương tự tôi đã không tìm thấy một cho con trỏ ngăn xếp.

Tôi sẽ đích thân nghỉ mát để lắp ráp nội tuyến vì bất cứ điều gì được viết sẽ có thể không được di chuyển anyway.

Ngoài ra, nếu tôi hiểu câu hỏi của bạn đúng, rất có thể là bản sao của this question do đó, nó cũng sẽ trả tiền để đọc những câu trả lời đó.

Edit: Nó phải là tương đương để trả lại địa chỉ của khung của hàm hiện tại có thể được thực hiện bằng cách sử dụng một GCC builtin function __builtin_frame_address (unsigned int level) linked earlier. Mã sẽ trông giống như sau:

int* recover() 
{ 
    return (int*)__builtin_frame_address(0); 
} 
+0

Không chỉ định con trỏ cho loại con trỏ sai chỉ không xác định khi bạn phân biệt nó? –

+0

Tôi không chắc đó là lý do tại sao tôi nói _ "có thể" _. Nếu bạn có một tài liệu tham khảo tôi sẽ sẵn sàng thay đổi tuyên bố của tôi. – nonsensickle

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