получение segfault, когда я возвращаю вектор указателя на структуру

Я пытался разбить строку и вставить маркеры в вектор указателей, чтобы структурировать следующим образом:

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

Проблема в том, что я получаю segfault и я точно не знаю. Раскол работает правильно. Но я не знаю, что не так.

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;
}
0
задан 13 August 2018 в 14:44

2 ответа

Ваш входной пакет размещен в стеке (локальная переменная). Когда вы выходите из функции split_queries (), экземпляр A уничтожается (деструктор называется) (более того, вы используете только один экземпляр A, объявленный в цикле). => вы должны выделить свой экземпляр A в куче (A * inputPacket = new A (item)) и не забудьте освободить его в главном или использовать вектор A (или share_ptr) вместо вектора A * ( который копирует каждый экземпляр в вектор)

0
ответ дан 15 August 2018 в 17:04
A inputPacket = {item};

Создает экземпляр A в локальной области действия while, поэтому он будет удален, когда область действия будет завершена. (т. е. один раз, когда заканчивается каждый цикл). Поэтому, когда вы используете указатели позже, они уже удалены.

Вам нужно самому управлять временем жизни переменной, вручную зарезервировав для них память:

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

и избегать использования указателя на локальный объект. Тем не менее, в этом случае вам тоже придется самому управлять временем жизни. Это означает, что вам нужно будет удалить указатели. Хорошая идея автоматизировать это с помощью unique_ptr Определите свой тип возврата как:

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

, затем создайте уникальные указатели и вставьте их в вектор:

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

Таким образом вы будете более безопасно работать с указателями.

1
ответ дан 15 August 2018 в 17:04

Другие вопросы по тегам:

Похожие вопросы: