2012-01-05 41 views
13

Nói rằng tôi có hai chức năng sau:địa chỉ trở về của biến cục bộ trong C

int * foo() 
{ 
    int b=8; 
    int * temp=&b; 
    return temp; 
} 

int * foo() 
{ 
    int b=8; 
    return &b; 
} 

tôi không nhận được bất kỳ cảnh báo cho cái đầu tiên (ví dụ: hàm trả về địa chỉ của biến cục bộ) nhưng tôi kn ow điều này là bất hợp pháp kể từ khi b biến mất khỏi ngăn xếp và chúng tôi còn lại với một con trỏ đến bộ nhớ không xác định.

Vì vậy, khi nào tôi cần phải cẩn thận khi trả lại địa chỉ của một giá trị tạm thời?

Trả lời

17

Lý do bạn không nhận được cảnh báo trong đoạn đầu tiên là vì bạn không (từ phối cảnh của trình biên dịch) trả lại địa chỉ cho biến cục bộ.

Bạn đang trả về giá trị int * temp. Mặc dù biến này có thể (và trong ví dụ này là) chứa một giá trị là một địa chỉ của một biến cục bộ, trình biên dịch sẽ không đi lên ngăn xếp thực thi mã để xem liệu đây có phải là trường hợp không.

Note: Cả hai đoạn là đều xấu, mặc dù trình biên dịch của bạn không cảnh báo bạn về các cựu. Không sử dụng phương pháp này.


Bạn nên luôn luôn cẩn thận khi trở về địa chỉ cho biến cục bộ; theo quy tắc, bạn có thể nói rằng bạn không bao giờ là.

static biến là trường hợp hoàn toàn khác, mặc dù đang được thảo luận trong this thread.

+1

cảm ơn! và thực tế là khi tôi in giá trị trả về trong chính nó sẽ cho tôi kết quả đúng nó thực sự có nghĩa là nó in rác? – mary

+3

Nó có nghĩa là bạn đang gọi những gì chúng ta thường gọi là * [hành vi không xác định] (http://en.wikipedia.org/wiki/Undefined_behavior) *, tức là. hành vi không được chỉ định trong tiêu chuẩn. –

-2

Đây là cả hai xấu, và một trình biên dịch tốt sẽ có thể phát hiện và cảnh báo về cả hai tình huống. Bạn có thể nhận được kết quả tốt hơn bằng cách chuyển mức cảnh báo thành mức tối đa (mà bạn luôn nên thực hiện) và bật tối ưu hóa.

+0

Trường hợp cụ thể, có thể. Nhưng có rất nhiều trường hợp tương tự liên quan đến việc xáo trộn địa chỉ đến và từ các biến khác (hoặc thông qua các hàm khác) mà trình biên dịch đơn giản sẽ không thể phát hiện được. Ngoài ra, tối ưu hóa hiếm khi tăng cơ hội phát hiện một vấn đề như vậy - nó chỉ làm tăng cơ hội của vấn đề có hiệu ứng quan sát được. – Rob

+0

Tất nhiên có những tình huống mà trình biên dịch không thể phát hiện, nhưng những trường hợp cụ thể này sẽ dễ dàng phát hiện được. Tối ưu hóa hoạt động vì nó làm giảm ví dụ đầu tiên về thứ hai. – harald

+1

Xin lỗi, không đúng sự thật. Có rất ít "cần" khi nói đến chất lượng thực hiện một trình biên dịch - đây là những quyết định của nhà cung cấp dựa trên phân tích chi phí/lợi ích của riêng họ, có thể không đáp ứng được các định kiến ​​của nhà phát triển. Nó cũng rất dễ xây dựng các ví dụ (ví dụ: một cuộc gọi hàm có thể thay đổi con trỏ) có nghĩa là tối ưu hóa mà bạn cho là có thể không khả thi - điều này cũng làm cho nó trở thành quyết định của nhà cung cấp về việc có tối ưu hóa những thứ đó hay không. – Rob

0

Cả hai ví dụ đều không chính xác như nhau. Tôi đoán là trình biên dịch của bạn không thấy nguy hiểm và do đó không đưa ra cảnh báo khi bạn lưu trữ địa chỉ trong một biến tạm thời.

1

tôi sẽ nói rằng bạn có thể trả về biến địa phương hoặc thay vì con trỏ tới IF nếu nó được phân bổ động bởi malloc, trong trường hợp đó bộ nhớ được sử dụng để lưu trữ biến muốn nằm trên stack nhưng trên heap và sẽ không bị xóa hoặc tái sử dụng sau khi thoát khỏi chức năng như nó diễn ra trong trường hợp các biến cục bộ tự động (được tạo mà không có malloc), tôi có đúng không?

0

Câu hỏi này có lẽ là một trong những thảo luận nhiều nhất về StackO. Dưới đây là hai câu trả lời từ các chủ đề tương tự trên StackO mà tôi thấy thú vị và có lẽ đã khiến tôi bỏ qua việc thực hiện sai các biến cục bộ mặc dù cơ hội nhận được sai (hành vi không xác định) rất mỏng.

Here is a simple answer

Tôi đặc biệt thích câu trả lời này.

Here is an example where this bad practice caused some real hardware damage

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