繁体   English   中英

C ++多线程应用程序上的内存损坏

[英]Memory Corruption on c++ multithreaded application

我正在开发一个多线程C ++应用程序,并开发了用于记录的模块。 日志记录模块是一个静态类,我使用Logger :: Log(字符串文件,字符串消息)进行调用,该类使用pair<string*,string*>填充静态队列。队列本身是一个queue<<pair<string*,string*>*> 就像我试图避免垃圾回收一样,所有内容都保存为指针,并认为指针变量需要特定的删除才能释放内存。

现在,当线程之一想要记录某些内容时,它将调用Log方法,该方法又追加到队列的末尾。

另一个线程遍历队列,弹出项目并将其写入指定的文件。

由于某些原因,写入文件的某些文本已损坏,因为我丢失了部分开头或消息末尾。

例如,如果我在Log方法内部调用Log(“ file”,“这是我的消息”),则我要附加一个时间戳,并创建一个新字符串,因为我认为原始字符串可能会被覆盖,但是仍然会发生。 问题在于,在某些情况下,写入文件的是时间戳记,加上消息的末尾。

这是Logger类的完整代码:

#include "Logger.h"

queue<pair<string*, string*>*> Logger::messages;

boost::mutex Logger::loggerLock;

void Logger::CleanOldFiles(vector<string> files){
    for (vector<string>::iterator it = files.begin(); it != files.end(); ++it) {
        string filePath = boost::filesystem::current_path().string() + "\\" + *it;
        int result = remove(filePath.c_str());
    }
}

void Logger::Init() {
    Logger::messages = queue<pair<string*, string*>*>();
    boost::thread workerThread(Logger::Process);
    //workerThread.start_thread();
}

void Logger::RawLog(string file, string message) {
    loggerLock.lock();
    string *f = new string(file);
    string *m = new string(message + "\n");
    messages.push(new pair<string*, string*>(f, m));
    loggerLock.unlock();
}

void Logger::Log(string file, string message) {
    loggerLock.lock();
    string *f = new string(file);
    string *m = new string(Functions::CurrentTime() + " (" + boost::lexical_cast<string>(boost::this_thread::get_id()) + "): " + message.c_str() + "\n");
    messages.push(new pair<string*, string*>(f, m));
    loggerLock.unlock();
}


void Logger::Process() {
    while (true) {
        if (Logger::messages.size() == 0) {
            boost::this_thread::sleep(boost::posix_time::milliseconds(200));
            continue;
        }
        loggerLock.lock();
        pair<string*, string*> *entry = messages.front();
        messages.pop();
        loggerLock.unlock();
        ofstream file(boost::filesystem::current_path().string() + "\\" + *(entry->first), ofstream::binary | ofstream::app);
        file.write(entry->second->c_str(), entry->second->length());
        file.close();
        delete entry->first;
        delete entry->second;
        delete entry;
        //cout << entry->second;
    }
}

我希望我已经足够清楚了...

我不明白为什么会这样,有人可以给我一些如何避免这种情况的提示吗?

提前致谢。

必须Logger::Log设置为MT安全的,否则您将获得两个或多个线程尝试同时记录某些内容。 使其成为MT安全的最简单方法是mutex

std :: queue不是线程安全的。 您需要锁定对所有共享对象的访问,或者使用TBB 提供的线程安全队列实现。

    if (Logger::messages.size() == 0) {

由于messages不是线程安全的,因此如果不持有锁,则不能在其上调用任何函数。 此外,您仍然缺少对string*delete调用。

您总是可以这样做:

void Logger::Process()
{
    while (true)
    {
        loggerLock.lock();
        if (Logger::messages.size() == 0)
           break;
        loggerLock.unlock();
        boost::this_thread::sleep(boost::posix_time::milliseconds(200));
    }
    pair<string*, string*> *entry = messages.front();
    messages.pop();
    loggerLock.unlock();
    ofstream file(boost::filesystem::current_path().string() + "\\" +
        *(entry->first), ofstream::binary | ofstream::app);
    file.write(entry->second->c_str(), entry->second->length());
    delete entry->first;
    delete entry->second;
    file.close();
}

但是,以供将来参考:

1)不要以这种方式使用指针。 只需使用成对的字符串队列即可。 指针什么都不买。

2)使用一些理智的同步机制,例如条件变量。 不要将sleep用于同步。

3)使用范围锁和RAII,这样您就不会忘记解锁。

对于可能为所有人提供帮助的工作,我深表歉意,但我更正了此问题。 这实际上不是内存损坏问题,我的假设使我寻找了没有问题的东西。

问题出在调用线程上,而在我创建日志字符串的表单上。 我用错误的方式串联了字符串...该死的其他编程语言;)

我正在做诸如Logger :: Log(“ Message:” + integerVariable)之类的事情,这实际上是在将字符串向右移动(至少我认为那是在做什么)。 当我将所有这些变量都转换为字符串时,一切开始起作用。 谢谢您的帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM