1

std :: ofstreamがスコープ外になるときに、セグメンテーション違反の問題が発生することはめったにありません。Logger.hには次の構造体があります。

        struct LogRequest
        {
            std::string line;
            std::string prefix;
        };

        struct FileInfo
        {
            std::string name;
            std::ofstream ofs;
            int lines;
            std::string ToString()
            {
                return (name + " exists");
        };

Logger.cppには、次の関数があります。

void Logger::Log(const std::string line, std::string prefix)
{
    pthread_mutex_lock(&mutex);
        if (file_map.find(prefix) == file_map.end())
        {
            OpenLogFile(prefix);
        }

        LogRequest* request = new LogRequest;
        request->line = line;
        request->prefix = prefix;
        message_queue.push_back(request);
    pthread_mutex_unlock(&mutex);
}

void Logger::OpenLogFile(const std::string& prefix)
{
    //get timestamp to use
    char timestamp[15];
    time_t now;
    time(&now);
    struct tm* current = localtime(&now);
    sprintf(timestamp, "%02u%02u%04u_%02u%02u%02u", (current->tm_mon+1),
        current->tm_mday,(1900 + current->tm_year), current->tm_hour,
        current->tm_min, current->tm_sec);

    FileInfo* info = new FileInfo;
    info->name = "logs/" + prefix + ".log_" + timestamp;
    info->ofs.open(info->name.c_str(), std::ios::out);
    info->lines = 0;

    file_map[prefix] = info;
}

void Logger::CloseLogFile(const std::string& prefix)
{
    delete file_map[prefix];
}

そして、Logger.cppのスレッドで、私は...

void Logger::WriteToFile()
{
    std::map<std::string, FileInfo* >::iterator it;

    while(run)
    {
        char timestamp[16];
        time_t now;
        time(&now);
        struct tm* current = localtime(&now);
        sprintf(timestamp, "%02u%02u%04u|%02u%02u%02u|", (current->tm_mon+1),
            current->tm_mday,(1900 + current->tm_year), current->tm_hour,
            current->tm_min, current->tm_sec);

        pthread_mutex_lock(&mutex);
            for(it=file_map.begin(); it != file_map.end(); ++it)
            {
                if(it->second->lines > MAX_LINES)
                {
                    CloseLogFile(it->first);
                    OpenLogFile(it->first);
                }
                else
                {
                    int written = 0;

                    while(!message_queue.empty() && written < MESSAGES_PER_WRITE)
                    {
                        LogRequest* request = message_queue.front();
                        message_queue.pop_front();

                        std::string line(timestamp, 16);
                        line.append(request->line);

                        FileInfo* info = file_map[request->prefix];
                        info->ofs << line << std::endl;
                        info->lines++;
                        written++;
                        delete request;
                    }
                }
            }
        pthread_mutex_unlock(&mutex);

        usleep(1000);
    }
}

私が抱えている問題は、FileInfoのstd :: ofstream ofsのデストラクタで、を実行しようとすると、セグメンテーション違反がスローされることがあるということCloseLogFileです。それは何度も動作します。そして、SEGフォールトが発生する前でも(さまざまなcoutステートメントを通じて)、std :: ofstreamが良好で、失敗しておらず、eofに到達しておらず、悪くないことを確認しました。また、file_map [prefix]が存在し、FileInfoのToString()も出力することで存在することを確認しました。これらはすべて、CloseLogFileで削除する直前にチェックされます。

私の質問は、SEGFAULTの理由に関するものです。

また、WriteToFile()で行がofstreamに出力される場合、LogRequestオブジェクトを削除しても問題ありません。のように、ラインで正確に何が起こっているのinfo->ofs << line << std::endl;ですか?

4

1 に答える 1

1

あなたの sprintf(timestamp...) 呼び出しは、未定義の動作を引き起こす 1 文字 (null) で上書きされるように見えます。それはスレッドスタック上にあり、ofsはヒープ上にあるため、主な問題である場合とそうでない場合があります...

于 2012-09-14T16:16:13.900 に答える