При запуске приведенного ниже кода я получаю Segmentation fault (core dumped).

Мне сказали, что сбои сегментов чаще всего возникают из-за плохих указателей. Я относительно новичок в этом языке, и с учетом сказанного я уверен, что делаю здесь что-то явно не так, но не могу заметить этого из-за моей неопытности и текущего уровня владения языком.

Приведенный ниже код создает vector из PeekDeque<StringWrap> объектов в методе main. Затем он передает указатель на vector функции testNewWord. Затем эта функция создает новый объект PeekDeque<StringWrap> и помещает его в конец vector. Ну, в любом случае это то, что я пытаюсь сделать!

#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>

using namespace std;

void testNewWord(string word, vector<PeekDeque<StringWrap> >* chains) {
    PeekDeque<StringWrap>* newpd = new PeekDeque<StringWrap>(100);
    newpd->pushFront(StringWrap(word));
    chains->push_back(*newpd);
}

int main(int argc, char* argv[]){   
    vector<PeekDeque<StringWrap> >* chains = new vector<PeekDeque<StringWrap> >(); 

    string word;

    string infileName = argv[1];
    ifstream* INFILEp = new ifstream(infileName.c_str(), ios_base::in);

    while ((*INFILEp) >> word) {
        testNewWord(word, chains);

    }

    INFILEp->close();

}

Что я здесь делаю не так? Возможно, удаление вызывается для нулевого указателя? Полегче со мной.

0
Bob Shannon 11 Мар 2014 в 02:49
3
Почему вы не можете просто использовать отладчик и выполнять свою программу шаг за шагом? Неужели это сложнее, чем спросить?
 – 
Andrey
11 Мар 2014 в 02:51
Я никогда не делал этого раньше - я новичок в этом. Что я должен искать?
 – 
Bob Shannon
11 Мар 2014 в 02:52
Для IDE с отладчиком. Выберите любую там связку бесплатных. Например Нетбинс.
 – 
Andrey
11 Мар 2014 в 02:53
1
Или, если вы работаете в Linux, используйте gdb. вы вызываете его с помощью gdb my_executable, а затем набираете run в командной строке. После сбоя введите backtrace, и он сообщит вам точную последовательность шагов, вызвавшую сбой.
 – 
aruisdante
11 Мар 2014 в 03:01
Спасибо за предложения по отладке, похоже, мне есть над чем поработать.
 – 
Bob Shannon
11 Мар 2014 в 03:37

3 ответа

Лучший ответ

Ни одно из мест, где вы используете указатель, на самом деле не должно быть (и не должно быть) указателем. Вместо этого они должны быть обычным объектом, а затем передаваться через ссылки .

Попробуйте заменить:

vector<PeekDeque<StringWrap> >* chains = new vector<PeekDeque<StringWrap> >();

Просто:

vector<PeekDeque<StringWrap> > chains;

А также

void testNewWord(string word, vector<PeekDeque<StringWrap> >* chains) {
     PeekDeque<StringWrap>* newpd = new PeekDeque<StringWrap>(100);

С участием:

void testNewWord(const string& word, vector<PeekDeque<StringWrap> >& chains) {
     PeekDeque<StringWrap> newpd(100);

Узнайте больше о том, когда следует использовать ссылки вместо указателей. Как правило, в C ++ используйте указатели только в том случае, если вы абсолютно не можете использовать ссылку. Вам также придется изменить все ваши -> обратно на ., потому что ссылки действуют так, как будто они являются фактическим объектом, а не указателем на него.

4
aruisdante 11 Мар 2014 в 03:03

Я не вижу, чтобы вы тестировали свой параметр argc. Что произойдет, если из командной строки не будет передан параметр?

2
Mauren 11 Мар 2014 в 02:53

Кажется, с вашим кодом все в порядке; то, что вы делаете, совершенно законно и правильно. Так что, возможно, что-то еще отсутствует на картинке, например, как вы вызываете свой код

ОДНАКО - у меня есть одно предложение

    PeekDeque<StringWrap>* newpd = new PeekDeque<StringWrap>(100);
    newpd->pushFront(StringWrap(word));
    chains->push_back(*newpd);   <----

Для последней строки вызывается конструктор копирования, и вы копируете вновь созданный объект в вектор. Это пустая трата ресурсов. Вы можете заменить vector<PeekDeque<StringWrap> >* chains на vector<PeekDeque<StringWrap>* >* chains и удерживать указатели. таким образом вы можете напрямую нажать на указатель и использовать время, потраченное на выделение нового объекта.

1
Pandrei 11 Мар 2014 в 03:17
Это очень полезное предложение, основанное на том, чего я в конечном итоге пытаюсь достичь, включая обработку большого количества данных!
 – 
Bob Shannon
11 Мар 2014 в 03:36
Хотя вы могли бы сделать то же самое без использования указателей, изменив метод testNewWord(), чтобы он вместо этого принимал PeekDeque<StringWrap>& deque, заполнив его и вернув void. Затем вы выделили указанный выше массив, поместив пустую двухстороннюю очередь в вектор chains и передав chains.back() методу. Если вас беспокоят проблемы с жизненным циклом, а это, как правило, когда вам нужно использовать указатели, вам следует вместо этого попробовать использовать shared_ptr/smart_ptr, чтобы выделение памяти выполнялось без необходимости сделать это вручную. Как написано, этот код пропускает память, как решето.
 – 
aruisdante
11 Мар 2014 в 03:40