多线程程序

时间:2016-05-11 19:00:42

标签: c++ c++11 ctypes

我遇到了一个将Windows中的共享库移植到Linux(CentOS 7.2)的奇怪问题。

该库用于python Web应用程序,并在多线程环境中运行。

当我在Windows上运行它(使用visual studio 2015编译)时,库没有问题,但是当使用多个线程运行时,它在linux上崩溃(segfaults)。我只能通过一个线程重现linux上的崩溃。

库在初始化方法中将数据加载到映射中。稍后,当其他线程尝试访问映射时,它无法读取映射所指向的内存。

以下是用于访问地图的方法之一。这个想法是第一次调用它时初始化地图,然后填充数据。对于连续调用,它只返回指向地图的指针,并且可以提取数据。

map<string, Airport*>& getIataAirports (){
    static auto iata_airports = new map<string, Airport*>;
    return *iata_airports;
}

当线程进入此方法时,它看起来都很好。

(gdb)p *iata_airports
$1 = std::map with 8763 elements = {["ARN"] = 0x7f34d0b3b8d8,...

但是在使用它的方法中它不起作用:

airport_t* getAirportByIATA(const char *iata) {
    string iata_s{iata};
    auto it = getIataAirports().find(iata_s);
    if (it != getIataAirports().end())
        return AS_C_AIRPORT(it->second);
    else
        return nullptr;
}

通过代码调试find方法返回一个迭代器,该迭代器不是映射的结尾,但it-&gt; second的值是伪值。

(gdb)p it
$2 = {first ="ARN", second = }

(gdb) p &(it->second)
Attempt to take address of value not located in memory.

这种行为可能是什么原因?再次注意,它在windows上完美运行(在linux中是单线程的)。

在linux上,使用g ++ 4.8.5和以下标志编译了库(没有警告)。 -std = c ++ 11 -Wall -Wextra -pthread -g -O2

使用python的ctype cdll.loadLibrary方法动态加载。

非常感谢有关如何继续调试此行为的任何提示!

更新

感谢目前为止的所有建议。

我还没能在纯c ++中重现这个错误。我尝试在一个线程中调用initialize方法,等待它完成,然后在另一个线程中访问该库,它可以正常工作。

我现在认为它与在python线程中加载的库有关。

网络服务器在单独的线程中处理每个请求。该库初始化为懒惰,意味着它在第一次使用时会被加载。由于这种设计,然后将在处理对服务器的第一响应的线程中加载和初始化库(即,不在主线程中)。然后,由于某种原因,当下一个线程要访问数据时,进程崩溃。再次只在Linux上,它在Windows上运行良好。我将在linux上编译一个python 2.7.11版本,看看它是否是python版本,这是罪魁祸首。

更新2

我应该补充一点,我设法通过在网络服务器的主线程中初始化库来实现它。我仍然想弄清楚为什么它在Windows上没有像它那样工作。

0 个答案:

没有答案