Abd*_*iJK 2 c++ segmentation-fault deque
我有一个项目中的一些代码似乎不起作用。
我正在尝试创建一个双端队列(结构体),它是类的静态成员。骨架/基本代码如下(我保留了所有数据类型 - my_typedef_fn 是通过 typedef-ing 函数指针获得的数据类型):
1.h文件:
class A {
struct Bstruct {
char * b_name;
my_typedef_fn b_func;
}
static std::deque<Bstruct> a_deque;
static void func();
}
Run Code Online (Sandbox Code Playgroud)
1.cpp文件:
std::deque<A::Bstruct> A::a_deque;
void A::func(char * name, my_typedef_fn fn) {
a_deque.push_front((Bstruct) {name, fn} ); // <<<< segfault !
}
Run Code Online (Sandbox Code Playgroud)
根据我的理解 - .h 文件只是声明内容(像往常一样) - .cpp 中的第一行初始化静态成员 a_deque - 函数 func 使用 push_back 将内容添加到双端队列
但我在调用 push_front 的行出现分段错误(使用 gdb 发现了这一点)。
另外,当我在 push_front 之前打印 a_deque.size() 时,我在 SEGFAULT 之前得到 4294967264 当我使用 for 循环计算双端队列中的元素数量时:
int counter = 0
for( std::deque<Bstruct> it = a_deque.begin(); it != a_deque.end(); it++, counter++ );
Run Code Online (Sandbox Code Playgroud)
我的计数器显示 0 个元素
所以,我不明白为什么会出现段错误,也不明白为什么 .size() 是一个很大的垃圾数
- 编辑1 - 添加函数调用方式:
2.cpp
#include "1.h"
void fn1() {
// some code
}
A::func("abc", fn1);
Run Code Online (Sandbox Code Playgroud)
它符合命令:
g++ -c -w -fpermissive -o 1.o 1.cpp
g++ -c -w -fpermissive -o 2.o 2.cpp
g++ -o final 1.o 2.o
Run Code Online (Sandbox Code Playgroud)
通常不可能简单地在全局范围内调用函数,就像您在2.cpp. 但你提到代码很旧,所以也许它是一个预标准的东西,或者是一个扩展。
无论如何,您已经显示了该函数正在 中调用2.cpp,而静态数据成员a_deque是在 中定义的1.cpp。这意味着您可能会陷入静态初始化顺序惨败的境地。全局变量(例如静态数据成员,显然还有这种奇怪的独立函数调用)按照它们在一个翻译单元(=.cpp文件)中出现的顺序进行初始化/执行,但它们在翻译单元之间的顺序是未指定的。
这意味着完全有可能在 的构造函数运行之前A::func()进行访问,这很可能导致段错误(因为双端队列的内部数据成员具有零甚至可能是随机值)。a_dequea_deque
要解决这个问题,您必须以某种方式摆脱这种情况。一种选择是将所有可以访问的全局代码a_deque移至1.cpp的定义之后并将其放置在a_deque.
另一种方法是a_deque用函数范围的静态变量替换,该变量保证在首次使用之前初始化:
1小时
class A {
struct Bstruct {
char * b_name;
my_typedef_fn b_func;
}
static std::deque<BStruct>& a_deque();
static void func();
}
Run Code Online (Sandbox Code Playgroud)
1.cpp
#include "1.h"
std::deque<A::BStruct>& A::a_deque()
{
static std::deque<BStruct> d;
return d;
}
void A::func(char * name, my_typedef_fn fn) {
a_deque().push_front((Bstruct) {name, fn} ); // <<<< hopefully no more segfault
}
Run Code Online (Sandbox Code Playgroud)