Заменить
const char *folder = GetFolderPath(s, data.IncludeSubFolders);
на
std::string folder( GetFolderPath(s, data.IncludeSubFolders) );
Поток начинается с копирования аргументов по значению, и вы копируете const char*
, который, вероятно, указывает на статический буфер в GetFolderPath
функция.Этот буфер будет перезаписываться при каждом вызове, который вы делаете, так что потоки, которые читают из него, могут получить или не получить то, что ожидали.
Обратите внимание, что вам не нужно делать emplace_back(std::thread(...
, поскольку вы пишете какАргументы emplace_back
передаются конструктору того типа, который содержит vector
, который в данном случае равен std::thread
.Вам также не нужно делать функцию потока static
, если вы действительно этого не хотите.Вы можете начать с лямбды, захватив this
и folder
копией.Еще одна вещь, которую вы можете заметить, заключается в том, что вывод искажается, когда многие потоки записывают в std::cout
одновременно.Вы можете защитить общие ресурсы (например, std::cout
) от одновременного доступа нескольких потоков, используя std::mutex
и std::lock_guard
.
Вот версия вашего класса с нестатическим методом потока и защитой для std::cout
:
#include <iostream>
#include <vector>
#include <cstring>
#include <mutex>
#include <thread>
const char* GetFolderPath() {
static std::vector<std::string> paths = {"this is a path", "here is another one",
"what do we have here", "mother of dirs",
"what did the tomatoe ..."};
static size_t idx = 0;
static char buf[256];
std::strcpy(buf, paths[idx].c_str());
idx = (idx + 1) % paths.size();
return buf;
}
class DtIndexer {
std::mutex mtx_cout; // std::cout mutex
public:
void ThreadedIndex(std::string folderPath) {
std::lock_guard lock(mtx_cout); // wait until this thread acquires the mutex
std::cout << "\t-> Indexing Folder: " << folderPath << "\n";
}
void UpdateIndex() {
std::vector<std::thread> threadList;
{ // lock_guard scope
std::lock_guard lock(mtx_cout); // acquire mutex
for(int i = 0; i < 50; ++i) {
// const char* folder = GetFolderPath();
std::string folder(GetFolderPath());
std::cout << "\t-> Adding Folder to Thread: " << folder << "\n";
// safe copy here --+ +--- thread runs here ---+
// | | |
// V V V
threadList.emplace_back( [this, folder] { ThreadedIndex(folder); });
// Δ
// |
// +-- no std::thread(... needed here
}
} // lock_guard releases mutex here
for(auto& t : threadList) t.join();
}
};
int main() {
DtIndexer a;
a.UpdateIndex();
}
Вы можете заменить строку folder
выше на const char*
и увидеть ту же проблему, что и у вас.