【问题标题】:stringstream and multithreading字符串流和多线程
【发布时间】:2016-07-05 13:33:59
【问题描述】:

我是多线程和 C++ 的新手,尝试在我的应用程序中使用线程来保存文件时遇到问题。代码如下:

#include <iostream>
#include <thread>
#include <fstream>
#include <vector>
#include <sstream>

using namespace std;

void writeCSV(vector<vector<double> > & vec, const char* filename) {

    ofstream output(filename);

    for (vector<vector<double> >::const_iterator i = vec.begin(); i != vec.end(); ++i) {
        for (vector<double>::const_iterator j = i->begin(); j != --i->end(); ++j) {
            output << *j << ", ";
        }
        output << *(--i->end()) << "\n";
    }


}

void testFn(int id) {
    std::ostringstream filename;
    vector<vector<double> > v(460, vector<double>(460,0));
    filename << "test" << id << ".csv";
    const char* fileStr = filename.str().c_str();
    cout << id << " : " << fileStr << endl;
    writeCSV(v, fileStr);

}


int main() {

    int numOfThreads = 180;
    std::thread t[numOfThreads];


    for (int i= 0; i< numOfThreads; i++) {
        t[i] = std::thread (testFn, i);
    }

    for (int i = 0; i< numOfThreads; i++) {
        t[i].join();
    }

    return 0;

}

当我运行这个程序时,它会在终端中打印出来(结果的子部分):

66 : 0�c
97 : test97.csv
90 : �'�dz
85 : �'�dz
43 : 
9695 : �'�dz
67 : �'�dz
93 : 
 : �_   ��
115 : test115.csv
144 : test144.csv
99 : test99.c0
68 : 
91 :  )�
98 : test98.c0

以及使用奇怪/错误的文件名保存文件。我猜这似乎是多线程和 ostringstream 的问题,但有什么想法为什么/如何解决?

【问题讨论】:

标签: c++ multithreading ofstream ostringstream


【解决方案1】:

这与多线程无关。

const char* fileStr = filename.str().c_str();

std::ostringstreamstr() 方法返回一个std::string 表示字符串流的内容。

std::stringc_str() 方法返回指向字符串数据的内部指针。

您缺少的是 c_str() 返回的指针仅在 std::string 被修改或被销毁之前有效,以先到者为准。

这里std::string 被立即销毁,因为它是一个临时值。因此,指向其内部数据的指针会立即失效。

您必须将返回的字符串存储在一个对象中,只要需要字符串数据,该对象就存在。简单地说:

std::string str = filename.str();
const char* fileStr = str.c_str();

str 继续存在于其自动作用域的剩余部分,这里足够长。

【讨论】:

    【解决方案2】:

    在您的文件初始化代码中,您有以下摘录:

    std::ostringstream filename;
    ...
    filename << "test" << id << ".csv";
    const char* fileStr = filename.str().c_str();
    

    最后一行是杀手。您正在做的是将您来之不易的filename,从中获取string 表示,从中提取c_str() 指针 - 然后破坏临时 string 对象。从那时起,任何访问fileStr 的尝试都会令人担忧。

    您需要做的是将临时string 对象分配给一个局部变量:

    filename << "test" << id << ".csv";
    std::string fileString = filename.str();
    const char* fileStr = fileString.c_str();
    

    这保证了临时 string 对象的生命周期 - 至少在函数结束之前!

    如果不这样做,fileStr 会指向未分配堆的中间 - 并且堆在它下面会发生变化。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-19
      • 2018-02-02
      • 1970-01-01
      • 2013-08-07
      相关资源
      最近更新 更多