C 独立线程错误

C++ detached thread bug

本文关键字:错误 线程 独立      更新时间:2023-10-16

花了一天之后试图解决一个神秘的错误,我寻求您的帮助。

当我运行代码时,您是否了解为什么要复制" Hello 3"输出?

#include <iostream>
#include <future>
#include <string>
#include <functional>
#include <type_traits>
#include <unistd.h>
template <class Fn, class... Args>
inline decltype(auto) runTerminateOnException(Fn&& fn, Args&&... args) {
    try {
        return std::invoke(std::forward<Fn>(fn), std::forward<Args>(args)...);
    } catch (...) {
        std::terminate();
    }
}
struct RunTerminateOnExceptionInvoker {
        template <class Fn, class... Args>
        decltype(auto) operator()(Fn&& fn, Args&&... args) const {
            return runTerminateOnException(std::forward<Fn>(fn), std::forward<Args>(args)...);
        }
};
template <class Fn, class... Args>
inline decltype(auto) runAsyncTerminateOnException(Fn&& fn, Args&&... args) {
    usleep(1000);
    return std::async(std::launch::async, RunTerminateOnExceptionInvoker(), std::forward<Fn>(fn), std::forward<Args>(args)...);
}
template <class Fn, class... Args>
inline void runOnDetachedThreadTerminateOnException(Fn&& fn, Args&&... args) {
    usleep(1000000);
    std::thread(RunTerminateOnExceptionInvoker(), std::forward<Fn>(fn), std::forward<Args>(args)...).detach();
}
struct A {
        template <class T>
        static void g(double x, const std::shared_ptr<std::string> &s) {
            T t{};
            std::cout << "g() : x = " << x << ", *s = " << *s << ", t = " << t << std::endl;
        }
        static void f(double x, std::shared_ptr<std::string> &s1, std::shared_ptr<std::string> &s2, std::shared_ptr<std::string> &s3) {
            printf("Coucou 1n");
            runAsyncTerminateOnException(g<double>, x, s1); // Working
            printf("Coucou 2n");
            auto future1 = runAsyncTerminateOnException(g<double>, x, s2); // Working
            printf("Coucou 3n");
            runOnDetachedThreadTerminateOnException(g<double>, x, s3); // Working
        }
};
int main() {
    auto s1 = std::make_shared<std::string>("Hello 1");
    auto s2 = std::make_shared<std::string>("Hello 2");
    auto s3 = std::make_shared<std::string>("Hello 3");
    A::f(10., s1, s2, s3);
    printf("Coucou 4n");
    return 0;
}

输出:

Coucou 1
g() : x = 10, *s = Hello 1, t = 0
Coucou 2
Coucou 3
g() : x = 10, *s = Hello 2, t = 0
Coucou 4
g() : x = 10, *s = Hello 3, t = 0
g() : x = 10, *s = Hello 3, t = 0

实时运行

谢谢

您在这里有未定义的行为。由于线程已脱离,因此您不能保证*s3的生存时间与独立线程一样长。main在您独立的工作人员线程执行之前结束,所有这些字符串都不在范围。

您必须按价值通过共享指针才能真正获得其参考计数能力。目前,对于每个测试,您只是通过参考来传递一个shared_ptr实例,这并不是特别有用。

如果您按值将它们传递到A::f中,则情况按预期工作。

我不能完全弄清楚编译器在您的情况下所做的魔术,并对这个具体的结果感到有些惊讶,但是幸运的是,我只能说"它是UB",然后将东西留在那里;(

坦率地说,我什至不确定让独立线程越过main的末端是否有效,但是我会让别人解决这个方面。