C中异常处理 - 使用setjmp()返回0? [英] Exception Handling in C - What is the use of setjmp() returning 0?

查看:133
本文介绍了C中异常处理 - 使用setjmp()返回0?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些有关setjmp / longjmp用法的问题 -


  1. 使用setjmp(jmp ___ buf stackVariables)返回0.这是一个默认值,我们不能影响。


  2. setjmp(stackVariables)的唯一重要意义是在stackVariable中推送堆栈。并且基本上0告诉我们堆栈是否成功地被push到stack_variables上。


  3. 它们是一个值,当值是非零(任何非零)时你从longjmp返回。什么是从lomgjmp返回,何时从longjmp返回,当您处理异常时。这是设置真的令人困惑。


  4. 有些请关注它来尝试/扔和抓住。如果可以提供setjmp / longjmp的一些很好的例子,那将是非常好的。


  5. longJmp像扔,它被称为在可以提出异常。


谢谢。

解决方案>

C99规范给出:


如果返回是来自直接调用,则setjmp宏返回值为零。如果
返回来自对longjmp函数的调用,则setjmp宏将返回非零
值。


所以1的答案是零表示你第一次调用 setjmp ,而非零表示它从 longjmp


  1. 它推动当前程序状态。在一个longjmp之后,状态被恢复,控制返回到它所调用的点,返回值不为零。


  2. C.它类似于 fork 返回不同的值,这取决于您是否处于原始进程,或者继承了环境的第二个进程,如果您熟悉的


  3. 尝试 / catch 在C ++中,将会在throw和catch之间的所有自动对象上调用析构函数。 setjmp / longjmp 不会调用析构函数,因为它们不存在于C.所以你是自己的就像在 malloc 的任何东西一样调用免费


有了这个条件,这个:

 包括< stdio.h> 
#include< setjmp.h>
#include< string.h>
#include< stdlib.h>

void foo(char ** data);
void handle(char * data);
jmp_buf env;

int main()
{
char * data = 0;

int res = setjmp(env);
//存储用于演示目的。
//在便携式代码中不存储
//结果,而是直接测试。

printf(setjmp returned%d\\\
,res);

if(res == 0)
foo(& data);
else
句柄(数据);

return 0;
}


void foo(char ** data)
{
* data = malloc(32);

printf(in foo\\\
);

strcpy(* data,Hello World);

printf(data =%s\\\
,* data);

longjmp(env,42);
}

void handle(char * data)
{
printf(in handler\\\
);

if(data){
free(data);
printf(data freed\\\
);
}
}

大致相当于

  #include< iostream> 

void foo();
void handle();

int main()
{
try {
foo();
} catch(int x){
std :: cout<<< 捕获<< x< \\\
;
handle();
}

return 0;
}

void foo()
{
printf(in foo\\\
);

std :: string data =Hello World;

std :: cout<<< data =<<数据<< \\\
;

throw 42;
}

void handle()
{
std :: cout<<< 在handler\\\
;
}

在C的情况下,你必须做明确的内存管理(尽管通常你'在释放它之前malloc'd它的功能之前调用longjmp,因为它使生活更简单)


I have a few questions relating to setjmp/longjmp usage -

  1. What is the use of setjmp(jmp___buf stackVariables) returning 0. It is a default, which we cannot influence.

  2. Is the only significance of setjmp(stackVariables) is to push the stack in stackVariables. And basically 0 tells us if the stack was pushed on stack_variables successfully.

  3. Their is one occasion when the value is non-zero (any non-zero) when you return from a longjmp. What is returning from a lomgjmp, when do you return from longjmp, when your exception is handled. This is setup is really confusing.

  4. Can some please relate it to try/throw and catch. And would be really great, if some good examples of setjmp/longjmp could be provided.

  5. Is longJmp like throw, and it is called just after the place where exception can be raised.

Thanks.

解决方案

The C99 spec gives:

If the return is from a direct invocation, the setjmp macro returns the value zero. If the return is from a call to the longjmp function, the setjmp macro returns a nonzero value.

So the answer to 1 is that a zero indicates you have called setjmp the first time, and non-zero indicates it is returning from a longjmp.

  1. It pushes the current program state. After a longjmp, the state is restored, control returns to the point it was called, and the return value is non-zero.

  2. There are no exceptions in C. It's sort-of similar to fork returning different values depending whether you're in the original process, or a second process which has inherited the environment, if you're familiar with that.

  3. try/catch in C++ will call destructors on all automatic objects between the throw and the catch. setjmp/longjmp will not call destructors, as they don't exist in C. So you are on your own as far as calling free on anything you've malloced in the mean time.

With that proviso, this:

#include <stdio.h>
#include <setjmp.h>
#include <string.h>
#include <stdlib.h>

void foo ( char** data ) ;
void handle ( char* data ) ;
jmp_buf env;

int main ()
{
    char* data = 0;

    int res = setjmp ( env ); 
    // stored for demo purposes. 
    // in portable code do not store 
    // the result, but test it directly.

    printf ( "setjmp returned %d\n", res );

    if ( res == 0 )
        foo ( &data );
    else
        handle ( data );

    return 0;
}


void foo ( char** data )
{
    *data = malloc ( 32 );

    printf ( "in foo\n" );

    strcpy ( *data, "Hello World" );

    printf ( "data = %s\n", *data );

    longjmp ( env, 42 );
}

void handle ( char* data )
{
    printf ( "in handler\n" );

    if ( data ) {
        free ( data );
        printf ( "data freed\n" );
    }
}

is roughly equivalent to

#include <iostream>

void foo ( ) ;
void handle ( ) ;

int main ()
{
    try {
        foo ();
    } catch (int x) {
        std::cout << "caught " << x << "\n";
        handle ();
    }

    return 0;
}

void foo ( )
{
    printf ( "in foo\n" );

    std::string data = "Hello World";

    std::cout << "data = " << data << "\n";

    throw 42;
}

void handle ( )
{
    std::cout << "in handler\n";
}

In the C case, you have to do explicit memory management (though normally you'd free it in the function which malloc'd it before calling longjmp as it makes life simpler)

这篇关于C中异常处理 - 使用setjmp()返回0?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆