返回 std::pair<vector<int>,double> 和 phtread_exit

Returning std::pair<vector<int>, double> with phtread_exit

我想 return 来自线程的 std::pair<std::vector<int>, double>

设置如下:

void* thread_run(void *);
int main(int argc, char* argv[]) {

     std::pair<std::vector<int>, double> value;

     pthread_t t;
     pthread_create(&t, NULL, thread_run, NULL);

     // wait
     void* out;
     pthread_join(t, &out);

     value = *(std::pair<std::vector<int>, double> *)out;
     free(out);

     use(value);
}

void* thread_run(void* arg) {
    std::pair<std::vector<int>, double> * out = (std::pair<std::vector<int>, double>*)
        malloc(sizeof(std::pair<std::vector<int>, double>));

    out->first  = calc1();
    out->second = calc2();

    pthread_exit(out);
}

问题是我造成了内存泄漏。 Valgrind 报告:

  1. 条件跳转或移动取决于单位化值并指向分配 out->first = calc1();

  2. 单元化值由堆分配创建并指向 malloc 行。

我正在使用 gcc 5.4.0 & C++ 11 和 pthread 库。我需要使用 pthread。我如何 return C++ STL 容器正确避免内存泄漏。

您的程序有未定义的行为,因为您为 out 分配了内存,但从未在此内存中构造对象。

然后 out->first = calc1(); 您尝试访问不存在的对象的成员,这会导致未定义的行为。

如果需要手动管理内存,那么需要使用new:

auto out = new std::pair<std::vector<int>, double>{};

然后用

删除它
delete static_cast<std::pair<std::vector<int>, double>*>(out);

请注意,您需要删除与创建指针相同类型的指针。您可能想在返回时立即进行转换。

在 C++ 中使用 malloc 几乎总是错误的,您应该使用 std::thread,它带有适当的可移植 C++ 接口,而不是 pthread 仅 POSIX-only C 接口优惠。

你只是 return 一个指向它的指针,就像其他任何东西一样。不要使用 malloc,使用 new。记得用正确的类型调用 delete

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

void* thread_run(void *);
int main(int argc, char* argv[]) {

     std::pair<std::vector<int>, double> value;

     pthread_t t;
     pthread_create(&t, NULL, thread_run, NULL);

     // wait
     void* out;
     pthread_join(t, &out);

     std::pair<std::vector<int>, double> *pntvalue = 
        static_cast<std::pair<std::vector<int>, double>*>(out);
     value = *pntvalue;
     delete pntvalue;

    std::cout << std::get<1>(value) << std::endl;
}

void* thread_run(void* arg) {
    std::pair<std::vector<int>, double> *out = new std::pair<std::vector<int>, double>{};
    out->first  = std::vector<int>{1};
    out->second = 2;
    return out;
}

if going the malloc route, would I have to give up on returning std containers from the thread?

一点也不,但请记住正确调用对象的构造函数和析构函数。这将是一些东西:

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

void* thread_run(void *);
int main(int argc, char* argv[]) {

     std::pair<std::vector<int>, double> value;

     pthread_t t;
     pthread_create(&t, NULL, thread_run, NULL);

     // wait
     void* out;
     pthread_join(t, &out);

     std::pair<std::vector<int>, double> *pntvalue = 
        static_cast<std::pair<std::vector<int>, double>*>(out);
     value = *pntvalue;
     pntvalue->~pair<std::vector<int>, double>();
     free(pntvalue);

    std::cout << std::get<1>(value) << std::endl;
}

void* thread_run(void* arg) {
    std::pair<std::vector<int>, double> *out = static_cast<
        std::pair<std::vector<int>, double> *>(malloc(sizeof(std::pair<std::vector<int>, double>)));
    new (out) std::pair<std::vector<int>, double>{};
    out->first  = std::vector<int>{1};
    out->second = 2;
    return out;
}

这个怎么样:不要在堆上分配。

您在 main() 中成功创建了一个名为 value 的对,具有自动存储期限。就用那个吧。

#include <vector>
#include <iostream>

#include <pthread.h>

void* thread_run(void *);

int main(int argc, char* argv[]) {
     std::pair<std::vector<int>, double> value;

     pthread_t t;
     pthread_create(&t, NULL, thread_run, &value);

     // Wait.  Do not need to retrieve results, which are available in `value`.
     pthread_join(t, nullptr);

     std::cout << "Results: " << value.first.at(1) << "; " << value.second << '\n';
}

void* thread_run(void* arg) {
    std::pair<std::vector<int>, double>& out = *static_cast<std::pair<std::vector<int>, double>*>(arg);

    out.first  = std::vector<int>{{1, 2, 3}};
    out.second = 42.0;

    pthread_exit(arg);
}

Runnable example on Coliru