2009-09-08 40 views
20

Câu hỏi của tôi nhằm vào hành vi của setjmp/longjmp liên quan đến biến cục bộ.setjmp/longjmp và biến cục bộ

đang

Ví dụ:

jmp_buf env; 


void abc() 
{ 
    int error; 

    ... 
    if(error) 
    longjmp(env); 
} 


void xyz() { 
    int v1;   // non-volatile; changed between setjmp and longjmp 
    int v2;   // non-volatile; not changed between setjmp and longjmp 
    volatile int v3; // volatile;  changed between setjmp and longjmp 
    volatile int v4; // volatile;  not changed between setjmp and longjmp 

    ... 

    if(setjmp(env)) { 
    // error handling 
    ... 
    return; 
    } 

    v1++; // change v1 
    v3++; // change v3 

    abc(); 
} 


int main(...) { 
    xyz(); 
} 

Các tài liệu của setjmp/longjmp nói:

"Tất cả các đối tượng truy cập có giá trị tính đến thời điểm longjmp() được gọi, ngoại trừ việc các giá trị của đối tượng thời gian lưu trữ tự động mà là cục bộ cho hàm chứa lời gọi tương ứng setjmp() không có loại đủ điều kiện dễ bay hơi và được thay đổi giữa lời gọi setjmp() và longjmp() không xác định. "

tôi thấy sau hai cách giải thích:

intepretation1:

biến địa phương được phục hồi, ngoại trừ những đều

  • non-volatile và
  • thay đổi

intepretation2:

biến địa phương được phục hồi, ngoại trừ

  • những người mà là non-volatile và
  • những người được thay đổi

Theo interpretation1 sau longjmp chỉ v1 là undefined. v2, v3, v4 được xác định. Theo giải thích2 sau khi longjmp chỉ v4 được xác định. v1, v2, v3 không xác định.

Điều nào là đúng?

BTW: Tôi cần câu trả lời chung ("di động") hợp lệ cho tất cả các trình biên dịch, tức là thử với một trình biên dịch cụ thể không hữu ích.

+0

Lưu ý thực hiện: Các biến được thay đổi và không bay hơi có thể giống như thời gian của longjmp, hoặc có thể được khôi phục về những gì chúng đang ở thời điểm setjmp, tùy thuộc vào việc tạo mã. Do đó 'không xác định'. Vì vậy, nếu chúng được * không * thay đổi, hai giá trị này giống nhau và đó là lý do tại sao các vars không thay đổi là an toàn. – greggo

Trả lời

10

Giải thích 1 là chính xác. Nếu Phiên dịch 2 được dự định, văn bản gốc sẽ sử dụng "hoặc được thay đổi" thay vì "và".

26

setjmp/longjmp được thực hiện bằng cách lưu sổ đăng ký (bao gồm cả ngăn xếp và mã con trỏ vv) khi lần đầu tiên được thông qua và khôi phục chúng khi nhảy.

tự động (hay còn gọi là "địa phương", Stack-phân bổ) biến mà không phải là 'bay hơi' thể được lưu trữ trong thanh ghi chứ không phải là trên stack.

Trong những trường hợp này, longjmp sẽ khôi phục các biến đăng ký này về giá trị của chúng tại điểm khi setjmp() được gọi đầu tiên.

Ngoài ra, trình biên dịch đặc biệt thông minh có thể tránh các biến có thể được suy ra từ trạng thái của biến khác và tính toán theo yêu cầu.

Tuy nhiên, nếu biến là tự động nhưng không được phân công một thanh ghi, nó có thể được thay đổi bằng mã giữa các setjmp và longjmp ..

dễ bay hơi là nói một cách rõ ràng các trình biên dịch không để lưu trữ các biến trong một thanh ghi . Vì vậy, trừ khi bạn nói một biến rõ ràng là biến động, nếu bạn thay đổi biến giữa setjmp/longjmp, giá trị của nó sẽ phụ thuộc vào các lựa chọn mà trình biên dịch tạo ra, và do đó không có gì bạn nên dựa vào ('không xác định').

+0

Và tôi đoán ngược lại, các biến tự động được khai báo là 'đăng ký' * có thể được lưu trong sổ đăng ký nhưng trình biên dịch có thể bỏ qua gợi ý, vì vậy điều này không thể đảm bảo chúng sẽ được khôi phục. – Michael

+0

@Michael Trên thực tế Thậm chí không có một đảm bảo rằng bất cứ điều gì là "phục hồi". Trường hợp 'bình thường' là các biến sẽ có giá trị mà chúng có, trước khi bạn gọi hàm bất kỳ dẫn đến longjmp. Trong một số trường hợp như đã thảo luận ở trên, chúng có thể bị "clobbered" bởi người khiếm thị khôi phục tất cả các thanh ghi cuộc gọi được thực hiện bởi setjmp/longjmp. Trong thực tế, điều này có nghĩa là, nếu được ghi đè, chúng có thể sẽ được khôi phục về giá trị 'setjmp', nhưng ngôn ngữ chỉ nói rằng chúng không xác định thay vì những gì bạn đặt chúng lần cuối. – greggo