返回指向结构的指针的向量时出现段错误

时间:2018-08-13 10:56:11

标签: c++ vector

我试图拆分一个字符串并将标记插入结构的指针向量中,如下所示:

#include <iostream>
#include <vector>
#include <regex>
#include <sstream>

using namespace std;

struct A {
    std::string pMessage;
};

std::vector<A*> splitQuery(A a) {
  std::vector<A*> split_queries;

  std::stringstream        ss(a.pMessage);
  std::string              item;

  while (std::getline(ss, item, ',')) {
    A inputPacket = {item};
    std::cout << item << std::endl;
    split_queries.push_back(&inputPacket);
  }

  return split_queries;
}

int main()
{
    A a = {"Hello,there"};
    std::vector<A *> split_queries = splitQuery(a);
    std::cout << split_queries.size() << std::endl;
    for (auto &s : split_queries) {
        std::cout << "elements " << s->pMessage << std::endl;
    }

    return 0;
}

问题是我遇到了段错误,我不知道为什么。拆分工作正常。但是我不知道怎么了。

Hello                                                                                                                                                             
there                                                                                                                                                             
2                                                                                                                                                                 
Segmentation fault (core dumped) 

更新和更正

我实际上是通过使用Uniquer_ptr更新代码的,因为它是动态创建的,所以在堆上对吗?因此它在push_back之后不会被销毁。

#include <iostream>
#include <vector>
#include <regex>
#include <sstream>
#include <memory>

using namespace std;

struct A {
    std::string pMessage;
};

std::vector<std::unique_ptr<A>> splitQuery(A a) {
  std::vector<std::unique_ptr<A>> split_queries;

  std::stringstream        ss(a.pMessage);
  std::string              item;

  while (std::getline(ss, item, ',')) {
    std::cout << item << std::endl;
    split_queries.push_back(std::unique_ptr<A>(new A({item})));
  }

  return split_queries;
}

int main()
{
    A a = {"Hello,there"};
    std::vector<std::unique_ptr<A>> split_queries = splitQuery(a);
    std::cout << split_queries.size() << std::endl;
    for (auto &s : split_queries) {
        std::cout << "elements " << s->pMessage << std::endl;
    }

    return 0;
}

3 个答案:

答案 0 :(得分:2)

您的问题归结为您使用 automatic 存储持续时间存储了指向变量的指针,并且尽管保留了指向该变量的指针,该变量也被销毁了。然后行

A inputPacket = {item};

声明了这种类型,并且在push_back语句之后超出了范围。

因此,您的代码的行为是未定义

一种可能的解决方法是使用std::vector<A>作为类型,但会牺牲一些值副本。由于您的A很容易被复制,因此起作用。如果不能接受,则使用智能指针类型的向量,例如std::unique_ptr<A>,并围绕A的每个实例的构造进行重构。

答案 1 :(得分:1)

A inputPacket = {item};

A的本地范围内创建while的实例,因此,当while范围结束时,它将被删除。 (即:每个循环结束一次。)因此,以后使用指针时,它们已被删除。

您必须通过手动为变量保留内存来管理变量的生命周期:

A *inputPacket = new A({item});

,并避免使用指向本地对象的指针。但是,在这种情况下,您也必须自己管理生命周期的结束。这意味着您必须删除某个地方的指针。要实现此目的,一个不错的主意是使用unique_ptr将返回类型定义为:

std::vector<std::unique_ptr<A> > 

然后创建唯一的指针并将其推入向量:

split_queries.push_back(std::make_unique<A>({item}));

这样,您将更安全地使用指针。

答案 2 :(得分:0)

您的 inputPacket 已分配在堆栈上(局部变量)。退出函数 split_queries()时,A实例被销毁(调用了析构函数)(此外,您仅使用循环中声明的A实例)。 =>您必须在堆上分配您的A实例( A * inputPacket = new A(item); ),并且不要忘记在主实例中分配它 或使用A(或share_ptr)的向量而不是A *的向量(它将复制向量中的每个实例)