Vì bạn đang gọi hành vi chưa được xác định, nên một trình biên dịch bị lỗi và một trình biên dịch khác xuất hiện để hoạt động. Cả hai đều đúng - đó là vẻ đẹp của hành vi không xác định.
Sự cố là ngữ cảnh đã lưu - jmp_buf
- chỉ còn hiệu lực miễn là chức năng được gọi là setjmp()
để đặt nó chưa được trả lại.
Tiêu chuẩn C99 (không còn là tiêu chuẩn hiện hành, nhưng từ ngữ này dường như không có thay đổi đáng kể) nói:
§7.13.2.1 Các longjmp
chức năng
Chức năng longjmp
phục hồi môi trường lưu theo yêu cầu gần đây nhất của macro setjmp
trong cùng một lời gọi chương trình với đối số jmp_buf
tương ứng. Nếu chưa có gọi như vậy, hoặc nếu chức năng chứa invocation của setjmp
vĩ mô đã chấm dứt thực hiện 208) trong thời gian chuyển tiếp, hoặc nếu gọi của setjmp
vĩ mô là trong phạm vi của một định danh với variably sửa đổi loại và thực hiện đã để lại phạm vi đó trong thời gian tạm thời, hành vi là không xác định.
208) Ví dụ, bằng cách thực hiện một tuyên bố return
hoặc vì một longjmp
cuộc gọi đã gây ra một chuyển đến một invocation setjmp
trong một chức năng trước đó trong tập hợp các cuộc gọi lồng nhau.
Mã của bạn đang thoát khỏi action_1()
gần như ngay lập tức, hiển thị jmp_buf
được lưu bởi setjmp()
vô giá trị.
Tôi tạo ra cuộc biểu tình này ít setjmp()
và longjmp()
một vài năm trước đây. Nó có thể giúp bạn.
/*
@(#)File: $RCSfile: setjmp.c,v $
@(#)Version: $Revision: 1.1 $
@(#)Last changed: $Date: 2009/10/01 16:41:04 $
@(#)Purpose: Demonstrate setjmp() and longjmp()
@(#)Author: J Leffler
@(#)Copyright: (C) JLSS 2009
*/
#include <stdio.h>
#include <setjmp.h>
#include <stdlib.h>
static jmp_buf target_location;
static void do_something(void)
{
static int counter = 0;
if (++counter % 10 == 0)
printf("---- doing something: %3d\n", counter);
if (counter % 1000 == 0)
{
printf("||-- doing_something: calling longjmp() with value -1\n");
longjmp(target_location, -1);
}
}
static void do_something_else(int i, int j)
{
printf("-->> do_something_else: (%d,%d)\n", i, j);
do_something();
if (i > 2 && j > 2 && j % i == 2)
{
printf("||-- do_something_else: calling longjmp() with value %d\n", (i + j) % 100);
longjmp(target_location, (i + j) % 100);
}
printf("<<-- do_something_else: (%d,%d)\n", i, j);
}
static void doing_stuff(void)
{
int i;
printf("-->> doing_stuff()\n");
for (i = rand() % 15; i < 30; i++)
{
int j;
do_something();
for (j = rand() % 10; j < 20; j++)
{
do_something_else(i, j);
}
}
printf("<<-- doing_stuff()\n");
}
static void manage_setjmp(void)
{
printf("-->> manage_setjmp()\n");
switch (setjmp(target_location))
{
case 0:
/* Initial return - get on with doing stuff */
doing_stuff();
break;
case -1:
/* Error return - terminate */
printf("<<-- manage_setjmp() - error return from setjmp()\n");
return;
default:
/* NB: not officially possible to assign the return from setjmp() */
printf("---- manage_setjmp() - non-error return from setjmp()\n");
doing_stuff();
break;
}
printf("<<-- manage_setjmp()\n");
}
int main(void)
{
printf("-->> main()\n");
manage_setjmp();
printf("<<-- main()\n");
return(0);
}
Tôi đã đọc một bài viết một thời gian trước về cách setjmp/longjmp thực sự làm hỏng trình tối ưu hóa và khi họ thoát khỏi chương trình họ đang làm việc để tăng tốc đáng kể. – Bill
Q: Phiên bản nào của MSVC++? Q: Chính xác nơi nó đã sụp đổ? Bạn đã thử chạy trong trình gỡ lỗi Visual Studio? Q: Có bất kỳ cảnh báo hoặc lỗi nào trong bản dịch MSVC++ của bạn không? – paulsm4
Phiên bản MSVC của tôi là năm 2008. sự cố trong longjmp. Vâng. không có lỗi và cảnh báo khi biên dịch. đó là một lỗi thời gian chạy – TZW