SIGNALSEGV (ошибка сегментации) вне векторного метода возврата

Я делаю оболочку с помощью Linux (WSL). По какой-то неизвестной причине, когда я возвращаю указатель структуры (который я сделал) в вектор, он вызывает SIGNALSEGV.

Это основные классы проблемного кода,

class TimeoutCommand : public BuiltInCommand {
public:
    bool background;
    std::string line;
    int pid;
    int duration;
    TimeoutCommand(const char* cmd_line);  //prepare line
    virtual ~TimeoutCommand() {}
    void execute() override; ////set alarm + fork + add to joblist + add to timelist
};

class TimeoutList{

public:
    struct TimeoutEntry {
        std::string line;
        int pid;
        time_t start_time;
        int duration;
        TimeoutEntry(int pid,time_t start_time,std::string line,int duration)
        :pid(pid),start_time(start_time),line(line),duration(duration)
        {};
    };

std::vector<TimeoutEntry*> TimeoutVec;
TimeoutList();
~TimeoutList() {
    for (TimeoutEntry *entry : TimeoutVec)
        delete entry;
}
void addCommand(TimeoutCommand* cmd); ////add new timeout
void timeoutCheck(); ////timout timedoutcommands

};

Это конструктор TimeoutCommand и строка, вызывающая проблемную функцию:

    TimeoutCommand::TimeoutCommand(const char *cmd_line)
        :BuiltInCommand(cmd_line)
{
    _parseCommandLine(cmd_line,args);
    background=_isBackgroundComamnd(cmd_line);
    for(int i=2;args[i]!=NULL;i++) {
        line +=args[i];
    }
    duration=stoi(args[1]);
}
void TimeoutCommand::execute() {
    alarm(duration);
    **SmallShell::getInstance().timouts->addCommand(this);**
...
...
...

И, наконец, вот проблемная функция:

void TimeoutList::addCommand(TimeoutCommand *cmd) {
time_t t= time(NULL);
if (t==-1){
    perror("smash error: time failed");
    return;
}
TimeoutEntry* entry = new TimeoutEntry(cmd->pid,t,cmd->line,cmd->duration);
**TimeoutVec.push_back(entry);**

}

Что вызывает ошибку сегментации? Я не вижу никаких странных ошибок указателя или чего-то подобного сразу.

выполнение этой команды будет выглядеть примерно так: timeout 3 sleep 10

Что будет cmd_line

Это часть std::vector, которая вызывает segfault

  push_back(const value_type& __x)
      {
    **if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)**
      {
        _GLIBCXX_ASAN_ANNOTATE_GROW(1);
        _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
                     __x);
        ++this->_M_impl._M_finish;
        _GLIBCXX_ASAN_ANNOTATE_GREW(1);
      }
    else
      _M_realloc_insert(end(), __x);
      }

**Проблемные строки отмечены ** **


person yellowcard123    schedule 26.04.2021    source источник
comment
По какой причине это std::vector<TimeoutEntry*> TimeoutVec; вместо std::vector<TimeoutEntry> TimeoutVec;? Или, если вы должны использовать указатели: std::vector<std::unique_ptr<TimeoutEntry>> TimeoutVec;?   -  person PaulMcKenzie    schedule 26.04.2021
comment
Думаю, не по какой-то особой причине, просто для семантики.   -  person yellowcard123    schedule 26.04.2021
comment
Причина, по которой это имеет значение, заключается в том, что вы устраняете необходимость в ручном управлении динамической памятью и, таким образом, устраняете потенциальную точку отказа. Для каждого вызова new в вашем приложении необходимо тщательно управлять памятью. Если у вас просто был std::vector<TimeoutEntry>, то не нужно вручную управлять памятью. Тогда строка, с которой у вас возникли проблемы, будет просто: TimeoutVec.push_back({cmd->pid,t,cmd->line,cmd->duration});, без вызова new.   -  person PaulMcKenzie    schedule 26.04.2021
comment
Может быть, но я проделывал нечто подобное в других местах кода и удалял все в desctrucor. и даже если это так, я не думаю, что это должно быть причиной сегментации.   -  person yellowcard123    schedule 26.04.2021
comment
но я проделал нечто подобное в других местах кода, и я удалил все в desctrucor. -- Мне не хочется сообщать вам плохие новости, но C++ так не работает. Он не смотрит на код и не говорит, что у меня есть x строк вызовов new и x строк вызовов delete, так что все в порядке. Помните, что существует поток программы, и вы не знаете или не уверены, как работает код. Это не так просто, как просто подсчитать количество вызовов new и delete в исходном коде.   -  person PaulMcKenzie    schedule 26.04.2021
comment
Во-вторых, код, который вы показываете, является частью класса. Если эти функции-члены не являются статическими, это означает, что показанный код должен выполняться с допустимым экземпляром TimeoutList. Мы понятия не имеем, допустим этот экземпляр TimeoutList или нет. Вот почему следует опубликовать минимально воспроизводимый пример.   -  person PaulMcKenzie    schedule 26.04.2021
comment
Ваш последний комментарий помог мне задуматься над проблемой, большое спасибо.   -  person yellowcard123    schedule 26.04.2021


Ответы (1)


Проблема заключалась в том, что я установил указатель на экземпляр TimeoutList без выделения нового места.

person yellowcard123    schedule 26.04.2021