2010-09-15 40 views
5

Tôi vừa bị cắn bởi một hành vi không xác định khó chịu do trả về một tham chiếu đến biến cục bộ.Trình biên dịch phát hiện trở về tham chiếu đến biến cục bộ

Chúng tôi biết đó là điều ác, và nói chung trình biên dịch in đẹp warning để cho chúng tôi biết như vậy ... cũng gcc (3.4.2) dường như không đẩy kiểm tra quá xa.

std::string get_env_value(std::string const& key); 

std::string const& get_phase() 
{ 
    std::string const& phase = get_env_value("PHASE"); // [1] 
    std::cout << "get_phase - " << phase << '\n'; 
    return phase;          // [2] 
} 

Biên dịch này không bị trục trặc, nhưng chúng tôi rơi vào vùng khó chịu của hành vi không xác định.

Dòng [1] là không sao vì tiêu chuẩn xác định rằng tuổi thọ của biến được liên kết với tham chiếu const nên được mở rộng để khớp với thời gian tồn tại của tham chiếu const.

Dòng [2] có vẻ okay quá ...

  • Đừng C++ thông số kỹ thuật bao gồm trường hợp này?
  • Có ai biết điều này thường được chẩn đoán không? (Tôi có thể bỏ lỡ một lá cờ hoặc một cái gì đó ...)

Dường như với tôi rằng phân tích tĩnh nên có thể nói rằng có sử dụng một "mở rộng tuổi thọ" cho [1], [2] là không an toàn, nhưng nó có thể nhận được xấu xí nhanh chóng tôi đoán ...

+0

Thiệt hại, đó là một trường hợp khó chịu! –

+1

Cuối cùng, có thể 'get_env_value()' trả về một tham chiếu đến một biến không nằm ngoài phạm vi, ví dụ như toàn cục, trong trường hợp đó mọi thứ sẽ ổn. – UncleBens

+0

@UncleBens: Đó là một điểm tốt – Chubsdad

Trả lời

5

Tiêu chuẩn không bao gồm [2]. Nó cho phép một rvalue được ràng buộc với một tham chiếu const, nhưng điều đó không cho phép bạn trả về một tham chiếu const và có tuổi thọ của rvalue nó được ràng buộc để mở rộng là tốt.

Và phân tích tĩnh thực sự có thể bắt được điều này, nhưng như mọi khi, đó là sự cân bằng. Trình biên dịch C++ đủ chậm, vì vậy các nhà biên dịch phải cân nhắc các lợi ích của việc phân tích tĩnh hơn nữa có thể cho phép chúng tạo ra các chẩn đoán tốt hơn, chống lại thời gian biên dịch tăng lên.

+0

Có thể thiết lập lint để bẫy không? –

+0

Tôi đồng ý rằng quá trình biên dịch đủ chậm, trình biên dịch cảnh báo về số lần trả về bị thiếu và trả về tham chiếu đến biến cục bộ, mặc dù tôi đã dự đoán rằng 'phase' sẽ tăng cảnh báo:/ –

2
  1. Không, tôi không nghĩ tiêu chuẩn đề cập/đề cập đến trường hợp cụ thể này.

  2. VS 2010 đưa ra cảnh báo biên dịch (/ Za,/W4).

Vì vậy, chắc chắn đây có vẻ là điều kiện được chẩn đoán.

Vì vậy, tôi tinh chỉnh các chức năng hơi như sau, chỉ để tạo ra nhiều con đường trở lại:

std::string const& get_phase() 
{ 
    std::string const& phase = get_env_value("PHASE"); // [1] 
    std::cout << "get_phase - " << phase << '\n'; 

    if(1){ 
     while(1){ 
      return phase; 
     } 
    } 
    return phase;          // [2] 
} 

Bây giờ, VS không báo cáo cảnh báo như trước đó.

Ví dụ, ngay từ cái nhìn đầu tiên, có vẻ dễ dàng cho trình biên dịch phát hiện và bắt được rằng không phải tất cả các đường dẫn đều trả về một giá trị. Nhưng trình biên dịch (ví dụ: VS) thì không.

int get_phase() 
{ 
    char ch; 
    if(ch){ 
     return 0; 
    } 
    // nothing returned from here. 
} 

Vì vậy, tôi đoán mã trong OP có thể có cùng phức tạp để chẩn đoán điều kiện như ví dụ được hiển thị ở trên, mặc dù tôi không chắc chắn. Điều tốt duy nhất là tiêu chuẩn là rõ ràng về trường hợp này.

$ 6.6.3/2 - "Chảy ra khỏi cuối của một hàm tương đương với lợi nhuận không có giá trị, điều này dẫn đến hành vi undefined trong một hàm giá trị trở ."

Quay lại mã trong OP, tôi đoán tiêu chuẩn không ủy quyền điều kiện này là điều kiện có thể chẩn đoán và do đó trình biên dịch được tự do làm như mong muốn. Về cơ bản nó được hiểu rằng các điểm tham chiếu được trả về cho một đối tượng đã bị hủy. Vì vậy, việc truy cập một đối tượng như vậy sẽ dẫn đến hành vi không xác định

+0

@Chusbad: hầu hết các trình biên dịch đều cảnh báo về các hàm không trả về (đôi khi lạm dụng, nhưng chỉ trong trường hợp góc). Tôi đã không thực sự mong đợi một lỗi ... nhưng một cảnh báo sẽ rất tốt đẹp :) –

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