bou*_*ika 7 c++ longjmp setjmp g++4.8
我大多说服自己,我遇到了一些g ++ 4.8.3错误,但我想我会首先问这个列表,因为我对setjmp/longjmp的经验很少.我将我的代码简化为以下foo.cxx:
#include <setjmp.h>
#include <string.h>
// Changing MyStruct to be just a single int makes the compiler happy.
struct MyStruct
{
int a;
int b;
};
// Setting MyType to int makes the compiler happy.
#ifdef USE_STRUCT
typedef MyStruct MyType;
#elif USE_INT
typedef int MyType;
#endif
void SomeFunc(MyType val)
{
}
static void static_func(MyType val)
{
SomeFunc(val);
}
int main(int argc, char **argv)
{
jmp_buf env;
if (setjmp(env))
{
return 1;
}
MyType val;
#ifdef USE_STRUCT
val.a = val.b = 0;
#elif USE_INT
val = 0;
#endif
// Enabling the below memset call makes the compiler happy.
//memset(&val, 0, sizeof(val));
// Iterating 1 or 2 times makes the compiler happy.
for (unsigned i = 0; i < 3; i++)
{
// calling SomeFunc() directly makes the compiler happy.
static_func(val);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我用g ++ 4.8.3编译这段代码.对我来说有趣的是,当我定义USE_STRUCT时,编译失败但成功使用USE_INT.代码中有注释进一步表明如何使用USE_STRUCT使编译成功.编译仅在g ++的-fPIC选项中失败,但这是我环境中的必需参数.
要查看编译错误:
g++ -DUSE_STRUCT -Wextra -Wno-unused-parameter -O3 -Werror -fPIC foo.cxx
Run Code Online (Sandbox Code Playgroud)
foo.cxx: In function ‘int main(int, char**)’:
foo.cxx:26:5: error: variable ‘val’ might be clobbered by ‘longjmp’ or ‘vfork’ [-Werror=clobbered]
Run Code Online (Sandbox Code Playgroud)
但是使用简单的int就可以了:
g++ -DUSE_INT -Wextra -Wno-unused-parameter -O3 -Werror -fPIC foo.cxx
Run Code Online (Sandbox Code Playgroud)
有人可以向我解释为什么val可能会被破坏,如果它是一个结构但不是如果它是一个int?如编码中的注释所示,对结构进行编译的其他方法的任何见解都会成功吗?或者这是否指向编译器错误?
任何见解和评论都非常感谢.
setjmp()保存当前堆栈。由于它是在 的声明之前调用的val,因此该变量不会位于保存的堆栈中。
之后setjmp(),变量被初始化,如果代码稍后跳回该setjmp点,变量将再次初始化,从而破坏旧变量。如果应该在旧实例上调用一个不平凡的析构函数,则这是未定义的行为(\xc2\xa718.10/4):
\n\n\n\n
setjmp如果将andlongjmp替换为setjmpand会为任何自动对象调用任何重要的析构函数,则 / 调用对具有未定义的行为。longjmpcatchthrow
旧实例的析构函数可能不会被调用。我的猜测是,gcc 不会对原始类型发出警告,因为它们没有析构函数,但会对更复杂的类型发出警告,这可能会出现问题。
\n| 归档时间: |
|
| 查看次数: |
2799 次 |
| 最近记录: |