字符串流和多线程
stringstream and multithreading
我是多线程和 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
以及使用 weird/wrong 文件名保存文件。我猜这似乎是多线程和 ostringstream 的问题,但是有什么想法 why/how 可以解决吗?
这与多线程无关。
const char* fileStr = filename.str().c_str();
std::ostringstream
的str()
方法returns一个std::string
表示字符串流的内容。
一个std::string
的c_str()
方法returns一个指向字符串数据的内部指针。
您缺少的是 c_str()
返回的指针仅在 std::string
被修改或被销毁之前有效,以先到者为准。
这里 std::string
立即被销毁,因为它是一个临时值。因此,指向其内部数据的指针会立即失效。
您必须将返回的字符串存储在一个对象中,只要需要字符串数据,该对象就存在。只需:
std::string str = filename.str();
const char* fileStr = str.c_str();
str
在其自动作用域的剩余部分继续存在,这里足够长。
在您的文件初始化代码中,您有以下摘录:
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
将指向未分配堆的中间 - 堆在其下方发生变化。
我是多线程和 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
以及使用 weird/wrong 文件名保存文件。我猜这似乎是多线程和 ostringstream 的问题,但是有什么想法 why/how 可以解决吗?
这与多线程无关。
const char* fileStr = filename.str().c_str();
std::ostringstream
的str()
方法returns一个std::string
表示字符串流的内容。
一个std::string
的c_str()
方法returns一个指向字符串数据的内部指针。
您缺少的是 c_str()
返回的指针仅在 std::string
被修改或被销毁之前有效,以先到者为准。
这里 std::string
立即被销毁,因为它是一个临时值。因此,指向其内部数据的指针会立即失效。
您必须将返回的字符串存储在一个对象中,只要需要字符串数据,该对象就存在。只需:
std::string str = filename.str();
const char* fileStr = str.c_str();
str
在其自动作用域的剩余部分继续存在,这里足够长。
在您的文件初始化代码中,您有以下摘录:
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
将指向未分配堆的中间 - 堆在其下方发生变化。