2016-07-05 7 views
2

私はマルチスレッドとC++が初めてで、ファイルを保存するアプリケーションでスレッドを使用しようとすると問題が発生します。コードは以下の通りである:私はこのプログラムを実行するとstringstreamとmultithreading

#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 

だけでなく、奇妙な/間違ったファイル名でファイルを保存します。これは、私が推測するマルチスレッドとストリームの問題だと思われますが、どのようなアイデアなのか/修正する方法は?

+0

データレースのような音。 –

+1

いいえ、データ競争ではありません。推測はまれに正しい答えにつながります。 –

+1

http://stackoverflow.com/questions/21034834/is-there-issue-will-stringstream-str-c-str – marcinj

答えて

4

これはマルチスレッドとは関係ありません。

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は、ここでは、十分な長さの自動範囲の残りの部分のために存在し続けています。あなたのファイルinitiialisationコードで

+0

素晴らしい!明確な説明をありがとう。 – Billy

2

、あなたは次の抜粋があります:

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

最終ラインがキラーされていることを。一時的stringオブジェクトを破壊をしてから- あなたがやっていることは、あなたの苦労して稼いだfilenameを取って、それからc_str()ポインタを抽出し、それからstring表現を取得しています。その時点から、fileStrにアクセスしようとする試みは激しいです。

あなたはローカル変数に一時的stringオブジェクトを割り当てている実行する必要があります。

一時的stringオブジェクトの寿命を保証
filename << "test" << id << ".csv"; 
std::string fileString = filename.str(); 
const char* fileStr = fileString.c_str(); 

- 少なくとも、関数の最後まで!

fileStrは割り当てられていないヒープの中央にポイントし、ヒープはその下に変更されます。