【问题标题】:Returning std::pair<vector<int>, double> with phtread_exit使用 phtread_exit 返回 std::pair<vector<int>, double>
【发布时间】:2019-11-23 20:22:20
【问题描述】:

我想从一个线程返回一个std::pair&lt;std::vector&lt;int&gt;, double&gt;

设置如下:

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-&gt;first = calc1();

  2. 统一化的值是由堆分配创建的,并指向 ma​​lloc 行。

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

【问题讨论】:

  • 使用new,而不是malloc
  • 我的理解是std::thread没有取消机制。我需要一个取消机制。此外,如果走 malloc 路线,我是否必须放弃从线程返回 std 容器?
  • 你应该放弃使用 malloc 创建 any C++ 对象。
  • 使用std::thread。对于取消机制,请执行pthread_cancel(std::thread::native_handle()) Here is a example
  • 感谢大家的宝贵意见,我只能选择一个答案,但您的所有反馈都非常有价值。我希望 SO 中有一种方法可以奖励所有做出贡献的人。

标签: c++ pthreads


【解决方案1】:

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

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

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

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

然后删除它

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

请注意,您需要删除与创建指针具有相同类型的指针。您可能希望在返回时立即进行演员表。

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

【讨论】:

    【解决方案2】:

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

    您成功地在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

    【讨论】:

      【解决方案3】:

      你只需返回一个指向它的指针,就像其他任何东西一样。不要使用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;
      }
      

      如果走 malloc 路线,我是否必须放弃从线程返回 std 容器?

      完全没有,但请记住正确调用对象的构造函数和析构函数。这将是一些事情:

      #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;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-10-29
        • 1970-01-01
        • 2021-09-03
        • 2014-03-03
        • 1970-01-01
        • 2021-03-19
        • 1970-01-01
        • 2013-08-18
        相关资源
        最近更新 更多