- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
通常 setjmp 和 longjmp 不关心调用栈——函数只是保存和恢复寄存器。
我想使用 setjmp 和 longjmp 以便保留调用堆栈,然后在不同的执行上下文中恢复
EnableFeature( bool bEnable )
{
if( bEnable )
{
if( setjmp( jmpBuf ) == 0 )
{
backup call stack
} else {
return; //Playback backuped call stack + new call stack
}
} else {
restore saved call stack on top of current call stack
modify jmpBuf so we will jump to new stack ending
longjmp( jmpBuf )
}
这种方法是否可行 - 有人可以为此编写示例代码吗?
为什么我自己相信它是可行的 - 是因为我已经编码/制作了类似的代码片段:
Communication protocol and local loopback using setjmp / longjmp
有两个调用堆栈同时运行 - 彼此独立。
但只是为了帮助您完成这项任务 - 我将为您提供获取 native 代码和托管代码的调用堆栈的函数:
//
// Originated from: https://sourceforge.net/projects/diagnostic/
//
// Similar to windows API function, captures N frames of current call stack.
// Unlike windows API function, works with managed and native functions.
//
int CaptureStackBackTrace2(
int FramesToSkip, //[in] frames to skip, 0 - capture everything.
int nFrames, //[in] frames to capture.
PVOID* BackTrace //[out] filled callstack with total size nFrames - FramesToSkip
)
{
#ifdef _WIN64
CONTEXT ContextRecord;
RtlCaptureContext( &ContextRecord );
UINT iFrame;
for( iFrame = 0; iFrame < (UINT)nFrames; iFrame++ )
{
DWORD64 ImageBase;
PRUNTIME_FUNCTION pFunctionEntry = RtlLookupFunctionEntry( ContextRecord.Rip, &ImageBase, NULL );
if( pFunctionEntry == NULL )
{
if( iFrame != -1 )
iFrame--; // Eat last as it's not valid.
break;
}
PVOID HandlerData;
DWORD64 EstablisherFrame;
RtlVirtualUnwind( 0 /*UNW_FLAG_NHANDLER*/,
ImageBase,
ContextRecord.Rip,
pFunctionEntry,
&ContextRecord,
&HandlerData,
&EstablisherFrame,
NULL );
if( FramesToSkip > (int)iFrame )
continue;
BackTrace[iFrame - FramesToSkip] = (PVOID)ContextRecord.Rip;
}
#else
//
// This approach was taken from StackInfoManager.cpp / FillStackInfo
// http://www.codeproject.com/Articles/11221/Easy-Detection-of-Memory-Leaks
// - slightly simplified the function itself.
//
int regEBP;
__asm mov regEBP, ebp;
long *pFrame = (long*)regEBP; // pointer to current function frame
void* pNextInstruction;
int iFrame = 0;
//
// Using __try/_catch is faster than using ReadProcessMemory or VirtualProtect.
// We return whatever frames we have collected so far after exception was encountered.
//
__try {
for( ; iFrame < nFrames; iFrame++ )
{
pNextInstruction = (void*)(*(pFrame + 1));
if( !pNextInstruction ) // Last frame
break;
if( FramesToSkip > iFrame )
continue;
BackTrace[iFrame - FramesToSkip] = pNextInstruction;
pFrame = (long*)(*pFrame);
}
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
}
#endif //_WIN64
iFrame -= FramesToSkip;
if( iFrame < 0 )
iFrame = 0;
return iFrame;
} //CaptureStackBackTrace2
我认为可以修改它以获得实际的堆栈指针(x64 - eSP 和 x32 - 已经有一个指针)。
最佳答案
从法律上讲,setjmp/longjmp
只能用于在嵌套调用序列中跳“回”。这意味着它永远不需要真正“重建”任何东西——在你执行 longjmp
的那一刻,一切都完好无损,就在堆栈中。您需要做的就是回滚在 setjmp
和 longjmp
之间积累的额外内容。
longjmp
自动为您执行“浅”回滚(即它只是将原始字节从堆栈顶部清除,而不调用任何析构函数)。所以,如果你想做一个适当的“深度”回滚(就像异常在调用层次结构中向上飞时所做的那样)你必须在需要深度清理的每个级别上 setjmp
,“拦截”跳转,手动执行清理,然后 longjmp
进一步调用层次结构。
但这基本上是“穷人异常处理”的手动实现。为什么要手动重新实现它?如果您想用 C 代码来做,我会理解。但为什么在 C++ 中?
附言是的,setjmp/longjmp
有时以非标准方式用于在 C 中实现协程,这确实涉及“跨”跳转和堆栈恢复的原始形式。但这是非标准的。在一般情况下,出于我上面提到的相同原因,用 C++ 实现会更加痛苦。
关于c++ - setjmp、longjump 和堆栈重建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40309904/
有没有办法使用 setjmp 来实现多任务处理?和 longjmp职能 最佳答案 这是所谓的用户空间上下文切换的一种形式。 这是可能的,但很容易出错,特别是如果您使用 setjmp 和 longjmp
我想在 Linux 环境中实现 POSIX 兼容的微线程。基本思路如下: 使用描述的技术 here , 为每个纤程分配新的栈空间。 使用 setitimer,创建将以固定时间间隔发送信号的计时器。此计
ISO/IEC 9899:1999 7.13.1.1 The setjmp macro Environmental limits 4 An invocation of the setjmp macro
我一直在尝试追踪我的代码(使用 setjmp)中的间歇性崩溃错误,并将其缩小为:在使用/O2 编译时显示,使用/O2/Oy- 消失,即仅显示省略帧指针。 http://msdn.microsoft.c
通常 setjmp 和 longjmp 不关心调用栈——函数只是保存和恢复寄存器。 我想使用 setjmp 和 longjmp 以便保留调用堆栈,然后在不同的执行上下文中恢复 EnableFeatur
下面的代码无法正常工作。谁能指出原因 #define STACK_SIZE 1524 static void mt_allocate_stack(struct thread_struct *mythr
一段代码在这里 jmp_buf mark; int Sub_Func() { int be_modify, jmpret; be_modify = 0; jmp
我的问题针对的是 setjmp/longjmp 关于局部变量的行为。 示例代码: jmp_buf env; void abc() { int error; ... if(error)
我正在尝试为 C OSX Carbon 多线程 应用程序安装“崩溃处理程序”。在 Windows 上,我可以轻松使用简单高效的 __try{} __except{} SEH of Windows效果很
我必须使用 setjmp/longjmp 实现用户级线程库作为作业。这是我写的代码: #include #include #include #include #include #includ
这个问题来自 SetJmp/LongJmp: Why is this throwing a segfault? 当我使用 Debug模式运行代码时,它确实按预期崩溃了。但是如果我使用 release
我不明白为什么在函数 middleFunc() 中,当 entry_point(arg) 在 if ( setjmp(中间) ) 语句。 #include #include
为什么 setjmp 不保存堆栈? 考虑以下代码: #include jmp_buf Buf; jmp_buf Buf2; void MyFunction() { for(int i = 0
#include #include #include #include static jmp_buf env_alrm; static void sig_alarm(int signo) {
在不久前的blog post中,Scott Vokes使用C函数setjmp和longjmp描述了与lua实现协程相关的技术问题: The main limitation of Lua corouti
在jpeglib ,必须使用 setjmp/longjmp 来实现自定义错误处理。 有很多资源说 setjmp/longjmp 不能很好地与 c++ 配合使用(例如 this question 中的答
我的问题针对的是 setjmp/longjmp 关于局部变量的行为。 示例代码: jmp_buf env; void abc() { int error; ... if(error)
我试图理解以下代码中的 setjmp: http://androidxref.com/4.2.2_r1/xref/frameworks/base/core/jni/android/graphics/Y
我正在调查setjmp/longjmp,发现setjmp 保存指令指针、堆栈指针等寄存器... 然而,我在这里没有得到的是,在调用 setjmp 和 longjmp 之间,不能修改线程本身堆栈中的数据
在 Why volatile works for setjmp/longjmp , 用户 greggo评论: Actually modern C compilers do need to know t
我是一名优秀的程序员,十分优秀!