使用pthreads时奇怪的std::string行为

Bizzare std::string behavior when using pthreads

本文关键字:std string 行为 pthreads 使用      更新时间:2023-10-16

我有一个奇怪的std::string问题。它与通过线程在结构中传递字符串有关。本质上,我通过连接字符串向量来构建字符串,并使用这个构建的字符串作为结构中的字符串。然后将结构体作为参数传递给线程,访问string成员变量,并尝试打印它。出现了令人难以置信的行为:

如果在线程创建之前先打印字符串,那么在线程运行时打印字符串。但是,如果在线程创建之前没有打印字符串,那么在线程运行时字符串不会打印,并且字符串的大小为0。有人能帮我解决这个问题吗?

#include <iostream>
#include <pthread.h>
#include <string>
#include <vector>

struct data
{
    std::string msg;
    int id;
};
std::string GetString(std::vector<std::string> &args);
void *F(void *vargp);
int main()
{
    using std::cout;
    using std::endl;
    std::vector<std::string> args;
    args.push_back(std::string("skip"));
    args.push_back(std::string("one"));
    args.push_back(std::string("two"));
    args.push_back(std::string("three"));
    args.push_back(std::string("four"));
    args.push_back(std::string("five"));
    data d;
    d.id = 123;
    d.msg = GetString(args);
    /* Removing the below commented line escapes the error. 
     * With the line commented the string has size 0 in F.
     * However when it is compiled and run, the string in F 
     * has its actual size and the correct output appear.
     * WHAT IS GOING ON?
     */
    // cout << "before: " << d.msg << endl;
    pthread_t tid;
    pthread_create(&tid, NULL, F, &d);
    pthread_exit(0);
}
void *F(void *vargp)
{
    using std::cout;
    using std::endl;
    pthread_detach(pthread_self());
    data d = *(data *)vargp;
    cout << d.msg << " " << d.id << endl;
}
std::string GetString(std::vector<std::string> &args)
{
    std::string str(args[1]);
    for (int i=2; i!=args.size(); i++)
        str += " " + args[i];
    return str;
}

我通过

编译函数
g++ test.cpp -pthread -o test
其中test.cpp是上述源文件的名称。

这是由于未定义的行为,因为变量d超出了作用域并在main函数中执行pthread_exit时被破坏。一旦原始变量超出作用域,线程函数中的指针就不再有效。

对于一个中间解决方案,动态地分配d。对于长期的解决方案,可以考虑使用std::thread