【问题标题】:Seg Fault resulting from push_back call on vector (threads linux)向量上的 push_back 调用导致的段错误(线程 linux)
【发布时间】:2013-10-21 18:42:57
【问题描述】:

所以我要做的是编写一个程序,该程序创建一系列子线程,这些子线程使用 pthread_create 方法获取参数,并使用传入的参数进行更多操作等等。我试图传入的参数是一个名为 reduce_args_ 的向量参数。这是结构 ReduceVector 的标头信息。

typedef vector<string> StringVector;

// a data structure to maintain info for the reduce task
struct ReduceArg
{
  ReduceArg (void);  // constructor
  ~ReduceArg (void); // destructor

  pthread_t tid;  // thread id of the reduce thread
  StringVector files_to_reduce; // set of files for reduce task
};

// more typedefs
typedef vector<ReduceArg *> ReduceVector;

现在问题来了,当我在这里调用 push_back 时:

for(int i = 0; i < num_reduce_threads_ ; i++){
            reduce_args_.push_back(phold);
        int count = 0;
        for(ShuffleSet::iterator it = shuffle_set_.begin(); it!=shuffle_set_.end(); ++it){
            string line = *it;
            string space = " ";
            string file = line.substr(0, line.find(space)) + ".txt";

            if (count < num_reduce_threads_){
                cout << reduce_args_[i+1];
                (reduce_args_[i+1] -> files_to_reduce)[count] = file;
                            //(reduce_args_[i+1] -> files_to_reduce).push_back(file);
             }
             count++;
            //cout << ((reduce_args_.back())->files_to_reduce).back()<< endl;
    }
}

这两种 push_back 方法都会导致段错误。洗牌集只是一个集合,正在输出字符串。并且如 .h 文件中所述,files_to_reduce 是一个字符串向量。所以我想要做的是访问 files_to_reduce 并 push_back 一个字符串到它上面,但是每次我遇到一个段错误。 reduce_args_obj 声明如下:

ReduceArg* plhold;
    reduce_args_.push_back(plhold);
    ((reduce_args_.back()) -> files_to_reduce).push_back("hello");
    for (int i = 0; i < this->num_reduce_threads_; ++i) {
      // create a placeholder reduce argument and store it in our vector
      (reduce_args_.push_back(plhold));
    }

谢谢你的帮助!!

【问题讨论】:

  • 不是直接的解决方案,但可以为您省去很多麻烦:如果您使用的是 C++11,请首选std::thread
  • 看起来您正在将未初始化的指针推入向量reduce_args_,然后尝试访问它。
  • 如果应用程序在 push_back 中崩溃,这意味着实际问题与向量无关,而是与您之前通过覆盖另一个数组的边界导致的堆损坏有关,在这种情况下,我们' d 需要更多代码才能为您指明正确的方向。这也可能是 Mgetz 所说的
  • 顺便说一句:写reduce_args_.back()-&gt;files_to_reduce.push_back("hello");
  • 基本上你们是对的,我忘了初始化它,结果访问了边界之外的未定义内存。然后我需要在循环中移动那个初始化语句。谢谢!

标签: c++ linux multithreading segmentation-fault push-back


【解决方案1】:

这个:

ReduceArg* plhold;
reduce_args_.push_back(plhold);

除非你隐藏了一些重要的代码,否则你推送的是一个未初始化的指针,所以下一行会导致混乱。

你可能是这个意思?

ReduceArg* plhold(new ReduceArg);

..但我怀疑您没有正确考虑对象的生命周期和您将其地址存储在向量中的对象的所有权。

一般来说,除非您确切地知道自己在做什么以及为什么要避免使用指针。发布的代码不需要它们,我建议你只使用这样的东西:

typedef vector<ReduceArg> ReduceVector;

....
reduce_args_.push_back(ReduceArg());
reduce_args_.back().files_to_reduce.push_back("hello");
for (int i = 0; i < num_reduce_threads_; ++i) {
  // create a placeholder reduce argument and store it in our vector
  (reduce_args_.push_back(ReduceArg());
}

【讨论】:

  • @MGetz 是的,但是:鉴于发布的代码,很难知道从哪里开始。我的猜测是他不应该首先存储指针。
  • 如果需要指针,我建议使用unique_ptr,通过声明typedef vector&lt;std::unique_ptr&lt;ReduceArg&gt;&gt; ReduceVector;
  • 就是这样!我没有意识到我需要用新的 ReduceArg 初始化 plhold!非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-18
  • 1970-01-01
相关资源
最近更新 更多