C++ 静态函数中的递归调用-gcc生成递归初始化错误异常

C++ 静态函数中的递归调用-gcc生成递归初始化错误异常,c++,recursion,gcc,static,C++,Recursion,Gcc,Static,我们有一些最近移植到Linux的代码(gcc 7.1-glibc 2.17)。我在下面包含了一些代码片段——我们在类头中使用这些宏,如下所示 在Windows上这一切都很好(仅限VS2019-64位)。然而,在gcc下,我们得到递归的初始化错误。我认为问题在于InitQueryMap(由BEGIN\u QUERY\u MAP宏生成)包含对D::InitQueryMap的递归调用,gcc可以防止这种情况。我认为,如果我们强迫它内联(我们已经尝试了所有的-f“内联”编译器选项),我们可以绕过这个问题

我们有一些最近移植到Linux的代码(gcc 7.1-glibc 2.17)。我在下面包含了一些代码片段——我们在类头中使用这些宏,如下所示

在Windows上这一切都很好(仅限VS2019-64位)。然而,在gcc下,我们得到递归的初始化错误。我认为问题在于InitQueryMap(由BEGIN\u QUERY\u MAP宏生成)包含对D::InitQueryMap的递归调用,gcc可以防止这种情况。我认为,如果我们强迫它内联(我们已经尝试了所有的-f“内联”编译器选项),我们可以绕过这个问题

想法

BEGIN_QUERY_MAP(SDSVector);
ADD_INTERFACE(awr::dfem::IVectorElemental<T>);
ADD_CLASS(SDVector);
 END_QUERY_MAP();

#define BEGIN_QUERY_MAP(C) \
public: \
const QueryMap& GetQueryMap() const override { static auto queryMap = C::InitQueryMap(); return queryMap;} \
const char* GetObjectPtr() const override { return (const char*) this;} \
const char* GetCName() override { return typeid(*this).name();} \
const std::type_info& GetTypeInfo() override {return typeid(*this); }\
static inline QueryMap InitQueryMap(int offset = 0) \
{ \
QueryMap qmap(10); \
auto cPtr = (C*)1

#define ADD_CLASS(D) { \
const auto &tmpqmap = D::InitQueryMap((int)((char*)((D*)cPtr) - (char*)cPtr) + offset); \
qmap.insert(tmpqmap.begin(), tmpqmap.end()); \
}

#define ADD_INTERFACE(I) \
qmap.emplace(typeid(I).name(), offset + int((char*)((I*)(cPtr)) - (char*)cPtr));  \
qmap.try_emplace(typeid(awr::IAWRUnknown).name(), offset + int((char*)((awr::IAWRUnknown*)((I*)(cPtr))) - (char*)cPtr )) 
开始查询地图(SDSVector);
添加_接口(awr::dfem::IVectorElemental);
添加_类(SDVector);
结束查询映射();
#定义开始查询映射(C)\
公众:\
const QueryMap&GetQueryMap()const override{static auto QueryMap=C::InitQueryMap();return QueryMap;}\
const char*GetObjectPtr()const override{return(const char*)this;}\
const char*GetCName()重写{return typeid(*this).name();}\
const std::type_info&GetTypeInfo()重写{return typeid(*this);}\
静态内联QueryMap InitQueryMap(int offset=0)\
{ \
QueryMap qmap(10)\
自动cPtr=(C*)1
#定义添加类(D){\
const auto&tmpqmap=D::InitQueryMap((int)((char*)((D*)cPtr)-(char*)cPtr)+偏移量)\
insert(tmpqmap.begin(),tmpqmap.end())\
}
#定义添加接口(I)\
qmap.emplace(typeid(I).name(),offset+int((char*)((I*)(cPtr))-(char*)cPtr))\
try_emplace(typeid(awr::IAWRUnknown).name(),offset+int((char*)((awr::IAWRUnknown*)((I*)(cPtr))-(char*)cPtr))

当函数具有局部静态变量时,从该变量的初始值设定项内部重新输入该函数是未定义的行为。如
int f(){static int x=f();return x;}
对于GCC,这种未定义的行为以
recursive\u init\u error
exception的形式表现出来。但在所示的代码中,我看不到这一点-问题可能出在其他地方。我们的应用程序是多线程的(使用Intel TBB)。如果多个线程同时调用GetQueryMap,gcc可能会抛出recursive_init_错误?不,局部静态变量的初始化保证是线程安全的。中的第一个线程将执行初始化,其余线程将阻塞,直到它完成。结果是我们必须链接pthreads