程序在一段时间后终止"std::bad_alloc"

Programm terminating "std::bad_alloc" after some time

本文关键字:bad alloc std 终止 程序 一段时间      更新时间:2023-10-16

我对此进行了思考,但找不到错误。谁能帮助我在哪里做不好的编程。
一个boost::thread通过套接字接收strings,将它们拆分为vector<string>并将它们分类到shared class内的正确变量中。其他线程从那里读取。我试图通过互斥锁使其线程安全,如下所示。
我感谢任何帮助,即使是小提示:)
程序终止的方式如下:

Looping...<enter to exit>
terminate called after throwing an instance of 'std::bad_alloc'
what():  std::bad_alloc
Aborted (core dumped)

这是相应的文件。它与ROS纠缠在一起,但这部分不应该是判决。

class shared
{
public:
    shared() : count(0) {/*emp. body*/ } //constructor
    void setvec(vector<string> &strVec, int type){
        boost::upgrade_lock<boost::shared_mutex> lock(mtx);
        boost::upgrade_to_unique_lock<boost::shared_mutex> uniqueLock(lock);
        switch(type) {
        case 1: typ1acc = strVec; setsensor[0] = true; break;
        case 2: typ2mag = strVec; setsensor[1] = true; break;
        case 3: typ3 = strVec; setsensor[2] = true; break;
        }/**/
    }
    vector<string> getvec(int type) {
        boost::shared_lock<boost::shared_mutex> lock(mtx);
        switch(type) {
        case 1: tmp = typ1acc; break;
        case 2: tmp = typ2mag; break;
        case 3: tmp = typ3; break;
        }
        return tmp;
    }
private:
    boost::shared_mutex mtx;
    vector<string> tmp;
    vector<string> typ1acc;
    vector<string> typ2mag;
    vector<string> typ3;
};
shared c; //class object

类是从多个 boost::线程调用的:

    //socket function which sorts vectors into shared class
    //this happens from one boost::thread 
    int type; //key sort by sensor type 
    vector<string> strVec;
    c.setvec(strVec,type);
    //multiple boost::threads call this to read the vectors
    //this happens from multiple boost::thread 
        strVec = c.getvec(type);
我认为在

函数外部使用tmp的问题在于,互斥析构函数将(或可以(在从tmp到永久变量的复制操作之前运行,从而导致一个小窗口,其中tmp可以被覆盖并导致潜在的数据竞争。

如果您创建简单的假互斥锁/字符串类,

这些类显示每个互斥锁/字符串类何时运行,则可以看到这一点。末尾的代码为我输出以下内容 (VC++ 2015(:

CSimpleString Raw Constructor (g_tmp)
CSimpleString Raw Constructor (result)
CFakeMutex Constructor
CSimpleString Copy Raw Operator (TestFunction)
CSimpleString Copy Constructor (TestFunction)
     CFakeMutex Destructor
     CSimpleString Copy Operator (TestFunction)
CSimpleString Destructor (TestFunction)
Result = TestFunction
重要

行缩进表示您的互斥锁在重要副本发生之前被销毁/释放。如果您将tmp放入函数中,则操作顺序似乎不会改变,但由于tmp是一个局部变量,因此不会发生潜在的数据争用。

用于测试这一点的非常基本的代码如下。

#include <string.h>
#include <vector>
class CFakeMutex 
{
public:
    CFakeMutex() 
    {
        printf("CFakeMutex Constructorn");
    }
    ~CFakeMutex()
    {
        printf("CFakeMutex Destructorn");
    }
};

class CSimpleString 
{
public:
    CSimpleString() {
        printf("CSimpleString Empty Constructorn");
    }
    CSimpleString(const char* pString) : m_String(pString) {
        printf("CSimpleString Raw Constructor (%s)n", pString);
    }
    CSimpleString(const CSimpleString& String) : m_String(String.m_String) {
        printf("CSimpleString Copy Constructor (%s)n", String.m_String.c_str());
    }
    ~CSimpleString()
    {
        printf("CSimpleString Destructor (%s)n", m_String.c_str());
    }

    CSimpleString& operator=(const CSimpleString& Src)
    {
        if (&Src == this) return *this;
        printf("CSimpleString Copy Operator (%s)n", Src.m_String.c_str());
        m_String = Src.m_String;
        return *this;
    }
    CSimpleString& operator=(const char* pString)
    {
        printf("CSimpleString Copy Raw Operator (%s)n", pString);
        m_String = pString;
        return *this;
    }
    std::string m_String;
};
CSimpleString g_tmp("g_tmp");

CSimpleString TestFunction()
{
    CFakeMutex Mutex;
    CSimpleString local_tmp("local_tmp");
    //local_tmp = "TestFunction";
    //return local_tmp;
    g_tmp = "TestFunction";
    return g_tmp;
}
int main()
{
    CSimpleString result("result");
    result = TestFunction();
    printf("Result = %sn", result.m_String.c_str());
    return 0;
}
Bo

Persson为我指出了正确的方向。我将vector<string> tmp放入使用它的函数中,并且运行稳定。

    vector<string> getvec(int type) {
        boost::shared_lock<boost::shared_mutex> lock(mtx);
        vector<string> tmp; //moved into the function
        switch(type) { ...}}

我无法解释为什么,但它运行稳定。如果有人可以对此进行扩展,那就太好了。