我正在使用Lua,它有一个C API,它的错误提升功能使用longjmps.在提出错误时,我首先构建一条描述错误的消息然后告诉Lua引发错误.例如
std::stringstream ss;
ss << "'" << function->cb->name << "' expects at most " << maxargs_all
<< " argument(s) and received " << nargs;
luaL_error(L, ss.str().c_str());
Run Code Online (Sandbox Code Playgroud)
我的理解是longjmp不会展开堆栈,所以我的stringstream
对象不会被破坏.如果我没记错的话,stringstream
其他C++库类通常会在堆上分配数据,当对象被销毁时会释放这些数据.但是,析构函数不会在这里调用,所以我认为这会导致内存泄漏.根据编写脚本的人,我可能会引发很多错误,从而泄漏大量内存.
我相信其他人需要解决类似的问题,但我找不到任何我想要的东西.很多地方说对象不会被破坏,但我认为必须有一种方法来确保释放内存?
我正在尝试测试我的两个函数,它们模仿setjmp和longjmp用于作业 - 这是非常困难的,因为我们不允许使用内置函数或汇编asm()来实现longjmp和setjmp函数.(是的,那真的是作业.)
问题:我一直收到错误的返回值.所以,简而言之,当main()调用foo()和foo()调用bar(),而bar()调用longjump()时,bar()不应该返回foo(),而是setjmp()应该返回main的返回值为1,应打印"error"(参见下面的main()).
相反,我的输出结果如下:
start foo
start bar
segmentation fault
Run Code Online (Sandbox Code Playgroud)
分段错误,我尝试通过使用malloc初始化指针*p来修复,但似乎没有做任何事情.虽然,分段错误,是我没有得到正确的返回值的原因?
码:
#include <stdio.h>
#include <stdlib.h>
int setjmp(int v);
int longjmp(int v);
int foo(void);
int bar(void);
int *add;
int main(void) {
int r;
r = setjmp(r);
if(r == 0) {
foo();
return(0);
} else {
printf("error\n");
return(2);
}
}
int _main(void) {
return(0);
}
int setjmp(int v)
{
add = &v;
return(0);
}
int longjmp(int v)
{
int *p;
p = &v;
*(p - 1) = …
Run Code Online (Sandbox Code Playgroud) 在jpeglib中,必须使用setjmp/longjmp来实现自定义错误处理.
有很多资源据说setjmp/longjmp与c ++不兼容(例如这个问题中的答案告诉他们确实与RAII一起使用),但是这个问题的答案是说析构函数被调用了.
我有这个例子(取自这里并修改了一下):
#include <iostream>
#include <csetjmp>
std::jmp_buf jump_buffer;
struct A
{
A(){std::cout<<"A()"<<std::endl;}
~A(){std::cout<<"~A()"<<std::endl;}
};
void a(int count)
{
std::cout << "a(" << count << ") called\n";
std::longjmp(jump_buffer, count+1); // setjump() will return count+1
}
int main()
{
// is this object safely destroyed?
A obj;
int count = setjmp(jump_buffer);
if (count != 9) {
a(count);
}
}
Run Code Online (Sandbox Code Playgroud)
在这个例子中,析构函数被调用(如我所料),但它是标准行为吗?或者它是编译器的扩展,还是简单的UB?
输出:
A()
a(0) called
a(1) called
a(2) called
a(3) called
a(4) called …
Run Code Online (Sandbox Code Playgroud) 在C参考手册,附录B介绍两种功能setjmp
,并longjmp
为一些所谓的非本地的跳跃.除了setjmp
保存状态信息和longjmp恢复的基本理解之外state
,我还无法理解此功能的确切流程和用例.
那么,这个功能到底完成了什么,它在哪里有用?
我正在将软件从嵌入式计算机移植到Linux机器上.(Ubuntu 14.04或Raspbian(raspberry pi))
原始程序使用setjmp/longjmp来处理超时和CTRL + C事件.它运行在具有单个主(一个线程)的微控制器上.
我正在尝试使用线程(pthreads)时有类似的行为.
我的想法是我想要超时或CTRL + C来重启无限循环.
原始代码正在执行类似下面的代码.我不介意用别的东西放弃setjmp/longjmp.(例如:try/catch或signal或pthread_kill,条件变量等.)
知道如何用C/C++实现类似的行为吗?
这是代码似乎部分工作,可能不推荐/破坏:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <setjmp.h>
// Define
#define TICK_NS_TIME (10000000) // 0.01 sec = 10 ms (100 times per second)
#define NS_PER_SEC (1000000000) // Nano sec per second.
#define TICK_PER_SEC (NS_PER_SEC/TICK_NS_TIME) // Number of tick per second (Ex:100)
#define TIMEOUT_COUNT (30*TICK_PER_SEC) // 30 seconds timeout (with 100 tick per second)
// Env set/long jmp
#define ENV_SZ (2)
#define …
Run Code Online (Sandbox Code Playgroud) 仅以i386为例,但是类似的问题适用于其他拱门。传统I386 jmp_buf
通过保存setjmp
由6个保存的寄存器:ebx
,esi
,edi
,ebp
,esp
,和eip
。其中,前4个是根据ABI保存的调用方,因此被调用的函数setjmp
本身将使用自己保存的值覆盖它们(该值在的第一个和第二个返回之间可能会发生变化setjmp
)。因此,将这些寄存器全部保存在其中有jmp_buf
什么意义?仅保存堆栈和指令指针不是很好吗?
编辑:我错误地混淆了保存主叫方和保存被叫方,这是造成混乱的全部原因。很抱歉浪费大家的时间。
我正在尝试使用setjmp/longjmp做一些简单的事情:要求用户多次按Enter键,如果用户插入其他内容,它将使用longjmp重新启动进程.
我正在使用计数器来检查它是否有效,此计数器在启动时为0,但是当使用longjmp时,计数器将重新启动为1.
#include <stdio.h>
#include <setjmp.h>
jmp_buf buffer;
char inputBuffer[512];
void handle_interrupt(int signal) {
longjmp(buffer, 0);
}
int main(int argc, const char * argv[]) {
int counter = 0;
counter = setjmp(buffer); // Save the initial state.
printf("Counter: %d\n", counter);
printf("\nWelcome in the jump game, press enter (nothing else!): \n");
while (fgets(inputBuffer, sizeof(inputBuffer), stdin)) {
if (*inputBuffer == '\n') { // If user press Enter
counter++;
printf("%d\n\n", counter);
printf("Again: \n");
} else {
handle_interrupt(0);
}
}
}
Run Code Online (Sandbox Code Playgroud)
pc3:Assignement 3 …
Run Code Online (Sandbox Code Playgroud) 据我了解,setjmp
保存当前上下文,并且应该在调用时还原它longjmp
。但是,下一段代码将显示15(我使用-g编译,没有进行任何优化)。我是不是误解了这种结构,还是想念其他东西?
#include <iostream>
#include <csetjmp>
std::jmp_buf jump_buffer;
int main()
{
int a = 0;
if (setjmp(jump_buffer) == 0) {
a = 15;
std::longjmp(jump_buffer, 42);
}
std::cerr << a << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
免责声明:仅出于好奇而尝试使用它。直到最近我阅读了一些有关NASA编码准则的论文,并提到禁止使用这种控制结构流程之后,我才听说过这种结构。
因为代码是混合的,所以同时使用c和c ++标记,并且我认为实际的相关功能与c重度用户更相关,而不是c ++ ...:/
我想使用longjmp来模拟goto指令.我有一个包含struct类型元素的数组DS(int,float,bool,char).我想跳到标有"lablex"的地方,其中x是DS [TOP] .int_val.我怎么处理这个?
示例代码:
...
jmp_buf *bfj;
...
stringstream s;s<<"label"<<DS[TOP].int_val;
bfj = (jmp_buf *) s.str();
longjmp(*bfj,1);
Run Code Online (Sandbox Code Playgroud)
但是我认为它有问题我该怎么办?
错误:
output.cpp:在函数'int main()'中:
output.cpp:101:错误:从类型'std :: basic_string,std :: allocator>'转换为无效的类型'__jmp_buf_tag(*)[1]'