setjmp和longjmp函数使用详解

AES-GCM加密认证模式:原理、优势与实战应用 在数据安全领域,加密与认证是保障信息机密性和完整性的两大基石。加密确保数据内容不被窃取,而认证则验证数据来源的真实性和传输过程中是否被篡改。传统的加密后认证方案如AES-CBC+HMAC需要串行处理,性能开销较大。GCM(伽罗瓦/计数器模式)作为一种认证加密(AEAD)方案,巧妙地将AES-CTR加密与基于伽罗瓦域的GHASH认证并行结合,实现了单次数据遍历即可同时完成加密和认证,大幅提升了处理效率。其核心价值在于高性能、支持附加认证数据(AAD)以及标准化程度高,广泛应用于TLS协议、无线网络安全和云存储 阅读详情

  非局部跳转语句—setjmp和longjmp函数。非局部指的是,这不是由普通C语言goto,语句在一个函数内实施的跳转,而是在栈上跳过若干调用帧,返回到当前函数调用路径上的某一个函数中。

#include <setjmp.h>
int setjmp(jmp_buf  env);

  返回值:若直接调用则返回0,若从longjmp调用返回则返回非0值

void longjmp(jmp_buf env,int val);

  在希望返回到的位置调用setjmp,此位置在main函数中,因为直接调用该函数,所以其返回值为0。setjmp参数evn的类型是一个特殊的类型jmp_buf,这一数据类型是某种形式的数组,存放着调用longjmp时能用来恢复栈状态的所有信息。因为需要在另一个函数中引用env变量,所以规范的处理方式是将env变量定义为全局变量。
  当检查到一个错误时,则以两个参数调用longjmp函数,第一个就是在调用setjmp时所用的env,第二个参数是具有非0值的val,它将成为从setjmp处返回的值。使用第二个参数的原因是对于一个setjmp可以有多个longjmp。
  下面我们可以看一个简单的例子:

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

void fun1(void);
void fun2(void);
jmp_buf jmpbuffer;

void main(void)
{
    int i = 0;
    int j = 0;
    i = setjmp(jmpbuffer);
    if(i==0)
    {
        printf("first run\n");
        fun1();
        fun2();
    }
    else
    {
        switch(i)
        {

            case 1:
                printf("In fun1\n");
                break;
            case 2:
                printf("In fun2\n");
                break;
            default:
                printf("unkown error\n");
                break;
        }
        exit(0);
    }
    return 1;
} 

void fun1(void)
{
    char *s = "hello";
    char *s1 = "Hello";
    if(strcmp(s,s1)!=0)
        longjmp(jmpbuffer,1);
}

void fun2(void)
{
    char *s = "world";
    if(strcmp(s,"World")!=0)
        longjmp(jmpbuffer,2);
}

函数运行结果是:

first run
In fun1

  在使用longjmp跳转到setjmp中时,程序主动的退出了!相当于抛出一个异常退出!其实这两个函数可以模拟C++中的异常函数:

使用setjmp和longjmp要注意以下几点:
  1、setjmp与longjmp结合使用时,它们必须有严格的先后执行顺序,也即先调用setjmp函数,之后再调用longjmp函数,以恢复到先前被保存的“程序执行点”。否则,如果在setjmp调用之前,执行longjmp函数,将导致程序的执行流变的不可预测,很容易导致程序崩溃而退出。
  2、不要假设寄存器类型的变量将总会保持不变。在调用longjmp之后,通过setjmp所返回的控制流中,程序中寄存器类型的变量将不会被恢复。寄存器类型的变量,是指为了提高程序的运行效率,变量不被保存在内存中,而是直接被保存在寄存器中。寄存器类型的变量一般都是临时变量,在C语言中,通过register定义,或直接嵌入汇编代码的程序。
  longjmp必须在setjmp调用之后,而且longjmp必须在setjmp的作用域之内。具体来说,在一个函数中使用setjmp来初始化一个全局标号,然后只要该函数未曾返回,那么在其它任何地方都可以通过longjmp调用来跳转到 setjmp的下一条语句执行。实际上setjmp函数将发生调用处的局部环境保存在了一个jmp_buf的结构当中,只要主调函数中对应的内存未曾释放 (函数返回时局部内存就失效了),那么在调用longjmp的时候就可以根据已保存的jmp_buf参数恢复到setjmp的地方执行。

  在APUE里面有一个很好的示例可以验证寄存器变量:

//#include "apue.h"
#include <stdio.h>
#include <setjmp.h>
#include <stdlib.h>

static void f1(int, int, int, int);
static void f2(void);

static jmp_buf  jmpbuffer;
static int      globval;

int main(void)
{
    int     autoval;
    register int    regival;
    volatile int    volaval;
    static int  statval;

    globval = 1; autoval = 2; regival = 3; volaval = 4; statval = 5;

    if (setjmp(jmpbuffer) != 0) {
        printf("after longjmp:\n");
        printf("globval = %d, autoval = %d, regival = %d,"
                " volaval = %d, statval = %d\n",
                globval, autoval, regival, volaval, statval);
        exit(0);
    }

    /*
     * Change variables after setjmp, but before longjmp.
     */
    globval = 95; autoval = 96; regival = 97; volaval = 98;
    statval = 99;

    f1(autoval, regival, volaval, statval); /* never returns */
    exit(0);
}

static void f1(int i, int j, int k, int l)
{
    printf("in f1():\n");
    printf("globval = %d, autoval = %d, regival = %d,"
            " volaval = %d, statval = %d\n", globval, i, j, k, l);
    f2();
}

static void f2(void)
{
    longjmp(jmpbuffer, 1);
}

不优化变量的时候:

$ gcc testjmp.c
$ ./a.out 
in f1():
globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99
after longjmp:
globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99

注意到上面的变量regival 虽然定义为寄存器变量,但因为没有优化,也不作为寄存器变量使用。

当优化变量的时候:

$ gcc -O testjmp.c
$ ./a.out 
in f1():
globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99
after longjmp:
globval = 95, autoval = 2, regival = 3, volaval = 98, statval = 99

  变量autoval 虽然没定义为寄存器变量,但因为有优化,编译器把它放在了寄存器里面。volaval 值符合预期,是因为告诉了编译器不要优化到寄存器。

NSIS教程(8): 基于第三方界面库的安装包界面 前面的几篇文章介绍了NSIS的传统界面的安装包和现代界面的安装包的制作方法,也提到了NSIS支持自定义页面(即使用page custom)的特性,自定义页面需要用户自己创建对话框、控件、添加控件响应等等,虽然NSIS提供了nsDialogs.nsh来支持这些功能,但使用起来还是不太方便(需要专门了解这个插件诸多用法),而且不够灵活,所以本文介绍一种终极的自定义界面的安装包解决方案,即完全使用第三方 阅读详情

相关推荐

基于STM32的工业I/O模块硬件电路实现

深入解析基于STM32的工业I/O模块硬件电路实现,涵盖关键电路设计与信号处理,突出硬件电路稳定性和工业级可靠性,适合嵌入式开发者参考。

weixin_35835018的博客 453

【C/C++ 跳转函数】setjmp 和 longjmp 函数的巧妙运用: C 语言错误处理实践

C标准库提供两个特殊的函数:setjmp() 及 longjmp(),这两个函数是结构化异常的基础,正是利用这两个函数的特性来实现异常。 所以,异常的处理过程可以描述为这样: 首先设置一个跳转点(setjmp() 函数可以实现这一功能), 然后在其后的代码中任意地方调用 longjmp() 跳转回这个跳转点上, 以此来实现当发生异常时,转到处理异常的程序上,在其后的介绍中将介绍如何实现。 setjmp() 为跳转返回保存现场并为异常提供处理程序,longjmp() 则进行跳转(抛出异常),setjmp()

探索C++编程的奥秘,分享深入的技术见解和实践,旨在激发读者创造力与解决问题的思维。 4377

Rstudio安装org.Hs.eg.db

自己也是个小白,初次安装org.Hs.eg.db碰到好多问题,步骤总结如下: 第一,instal.packages()安装,不行则换 BiocManager::install() 第二,如BiocManager不成,说明不是最新版本,可按提示安装最新版 BiocManager::install(version = '3.13') #由于R版本较新,按照提示中的相关信息,安装最新版本的 第三,再次安装 BiocManager::install("org.Hs.eg.db") 第四,之后每个人.

ZH_DDong的博客 2万+

C语言中setjmp函数和longjmp函数

setjmp和longjmp的使用

wjp1792342241的博客 1227

Linear超高PSRR线性稳压器-典型应用电路解析

本文整理完了LT3045数据手册内所有的典型应用电路,试图让沉默的电路开口,简单介绍了他们这样做的目的和原理,从中我们可以更加熟悉这颗经典芯片的应用。但也有一些电路并没有搞懂,遗留下了不少问题。

硬件工程师笔记 2939

基于STC8G1K08A单片机的7位PWM输出程序(PCA功能实现呼吸灯效果)

摘要:本文展示了基于STC8G单片机的PWM占空比控制实现。通过定时器0中断每5ms调整占空比(0-127范围),实现呼吸灯效果。关键代码包括:1)PWM初始化(7位PWM模式);2)定时器配置(1ms中断);3)主循环根据标志位动态调整占空比。硬件采用P5.4引脚输出PWM信号,通过direction标志实现占空比自动增减循环。该方案适用于LED亮度调节等场景,系统时钟24MHz,采用12T模式。

weixin_74013772的博客 864

7_13:验证longjmp后变量的值

一源代码:      1  #include "apue.h"      2  #include      3      4  void f1(int,int,int,int);      5  void f2(void);      6      7  static jmp_buf jmpbuffer;      8  static int globval;      9

YOU CAN IF YOU BELIEVE YOU CAN 438

【扣子AI开发】如何开发一个图像生成智能体?

【扣子AI开发】如何开发一个图像生成智能体,从创建到发布

tl437002770的博客 2427

在C语言环境下,使用setjmp库来实现简单的try-catch异常处理块

/CPL try-catch-finally block自实现

ClassZheng的博客 515

2 硬件工程师笔面试高频知识考点真题解析——电容

本文全面解析了电容在电子电路中的关键应用与技术要点。主要内容包括:1. 电容选型核心要素:介质材质(陶瓷/电解/钽电容等)、容值精度、耐压等级、温度特性、ESR参数等,不同应用场景(滤波/去耦/谐振等)的选型策略。2. 典型电路应用原理:详细阐述去耦电容布局规则、晶振负载电容作用、共射放大电路旁路电容功能,以及RC电路的滤波/定时等应用。3. 特殊问题解决方案:MLCC啸叫机理与对策、寄生电容影响与消除、高速信号线电容使用禁忌等工程实践难题。4. 安全规范要点:X/Y电容的区别与选用、电解/钽电容防反接措施

XU157303764的博客 1557

Linux LT8912b调试记录(MIPI转LVDS/HDMI)

本文记录了在RK3588平台上使用LT8912B芯片实现MIPI转LVDS/HDMI的调试过程。主要包含设备树配置、驱动代码实现及常见问题解决。调试重点包括:1)正确配置1280x800分辨率的LVDS屏幕参数;2)确保I2C总线正常通信;3)解决花屏、图像抖动、黑屏等问题,涉及lane-rate计算、同步信号极性调整及MIPI模式选择。文中提供了详细的寄存器配置代码和故障排查方法,特别强调了I2C通信验证和电压匹配的重要性。通过参数优化和多种模式测试,最终实现了稳定的视频输出转换。

qq_45147279的博客 1086

setjmp和longjmp

此文是学习 C专家编程 中的笔记。 setjmp和longjmp是C语言所独有的,它们部分弥补了C语言有限的转移能力。 函数说明(来自wiki百科): int setjmp(jmp_buf env) 建立本地的jmp_buf缓冲区并且初始化,用于将来跳转回此处。这个子程序保存程序的调用环境于env参数所指的缓冲区,env将被longjmp使用。如果是从setjmp直接调用返

cscmaker的专栏 6206

fanuc机器人KAREL程序间参数的传递

之前的课程中讲述过KAREL程序中函数参数的传递,而控制工业机器人的动作只能通过控制TP程序来实现,所以在实际应用中就会出现在不同程序间进行参数的传递。尤其是对于有模块化编程的思想的设计者,更有这种迫切的要求。所以本次课程来讲解一下如何实现在不同程序之间进行参数的传递。 本次课程分为两个部分,以讲解在不同类型程序间进行参数传递的实现方式。 1、TP程序之间传递参数; 2、TP与PC程序之间传递参数。

haier123888的博客 2695

setjmp和longjmp函数

int setjmp(jmp_buf jmpb) 设置缓冲区来保存堆栈的内容,将保存的上下文存入进程的自身的数据空间(u区),并继续在当前的上下文中执行,一旦碰到了longjmp,进城就从该进程 的u区,取出先前保存的上下文,并恢复该进程的上下文为先前保存的上下文。这时核心将使得

zcfriends的专栏 331

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

setjmp和longjmp跨函数跳转

setjmp和longjmp函数可以实现跨函数跳转 #include <setjmp.h> int setjmp(jmp_buf env); setjmp的参数env是一个特殊类型 jmp_buf。这一数据类型是 某种形式的数组,其中存放在调用longjmp时能用来恢复栈状态的所有信息。一般, env变量是个全局变量,因为需从另一个函数中引用它。 返 回 值: 若直接调用则为0,若从 ...

weixin_43781183的博客 471

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

setjmp和longjmp函数使用方法

非局部跳转语句—setjmp和longjmp函数。非局部指的是,这不是由普通C语言goto,语句在一个函数内实施的跳转,而是在栈上跳过若干调用帧,返回到当前函数调用路径上的某一个函数中。#include <setjmp.h> Int setjmp(jmp_buf env);返回值:若直接调用则返回0,若从longjmp调用返回则返回非0值 Void longjmp(jmp_buf env,int

码农小张 748

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

第五章_进程 : 函数setjmp和longjmp

函数setjmp和longjmp 非局部跳转语句—setjmp和longjmp函数。非局部指的是,这不是由普通C语言goto,语句在一个函数内实施的跳转,而是在栈上跳过若干调用帧,返回到当前函数调用路径上的某一个函数中。 #include Int setjmp(jmp_buf env); 返回值:若直接调用则返回0,若从longjmp调用返回则返回非0值 Void longjmp(jmp_buf env,int val); 在希望返回到的位置处调用setjmp,此位置在main函数中,因为直接调用

matafeiyanll的博客 324

关于setjmp和longjmp函数

现在可以讨论一下setjmp()和longjmp()的用途,因为它们是通过操纵过程活动记录实现的。许多程序员新手并不知道这个强大的机制,因为它是C语言所独有的。它们部分弥补了 C语言有限的转移能力。这两个函数协同工作,如下所示; setjmp(imp buf j)必须首先被调用。它表示“使用变量j记录现在的位置。函数返回零。longjmp(jmp bufj, int i)可以接着被调用。它表示“回...

weixin_45045399的博客 464

C语言:setjmp和longjmp函数使用详解

转载自: https://www.runoob.com/cprogramming/c-standard-library-setjmp-h.html      https://blog.youkuaiyun.com/chenyiming_1990/article/details/8683413 1、C 标准库 - &lt;setjmp.h&gt; 简介 setjmp.h 头文件定义了宏 setjmp()、函数 ...

houxiaoni01的博客 5402

浅谈setjmp与longjmp函数

在C语言中,用于跳转的goto语句,只能够用在同一个函数内部的跳转。而setjmp 与 longjmp的结合使用,却可以实现在不同程序之间的跳转。让我们先来看一下函数原型吧: #include int setjmp(jmp_buf env) void longjmp(jmp_buf env, int val); 这两个函数都要包含头文件setjmp.h。而且它们在处理出现在深层函数嵌套的错误情况时很有用处。 setjmp这个函数很有意思,虽然是一个函数,可是却可以返回两个不同的值。当第一次直接调用setjm

caianye的专栏 1381

linux——setjmp()和longjmp()函数的使用

setjmp()和longjmp()函数 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;~~~~~&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;与刺激的abort()和exit()相比,goto语句看起来比较适合处理异常的情况。不过,goto是本地的,只能跳到所在函数内部的标号上,而不能将控制权转移到所在程序的任意地点。 &nbsp;&nbsp;&nbsp;&nbsp;

夜风的博客 2035

Linux 函数跳转 setjmp和 longjmp的使用

当longjmp函数传回0时,系统会自己用1替代,即带回的ret为1.goto不可以跨函数跳转,函数setjmp 和 longjmp 可以。正常调用代码: main-> a -> b -> c。结果:对比可知返回时的打印都不打印了。

m0_72812391的博客 306

展示函数setjmp()和longjmp()的用法

//展示函数setjmp()和longjmp()的用法 #include <setjmp.h> #include "tlpi_hdr.h" #define EXIT_SUCESS 0 static jmp_buf env; static void f2(void) { longjmp(env,2); } static void f1(int argc) { if (argc == 1) longjmp(env,1); f2(); } int main.

liao__ran的博客 315
上一篇: 数字电视业务PSI-SI学习系列
下一篇: Linux framebuffer显示bmp图片
xianjian_x
博客等级 码龄14年 231粉丝 43原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值