2016-02-05 2 views
-1

EDIT: Я получил решение и поставил свой новый код ниже. Спасибо за вашу помощь!Что это за ошибка? Test: malloc.c: 2388: sysmalloc: Assertion ... failed "

У меня есть массив нулевых указателей, и я пытаюсь установить элемент массива в определенный индекс, чтобы указать на объект класса, я создал, но я в конечном итоге с этой ошибкой:

test: malloc.c:2388: sysmalloc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 *(sizeof(size_t))) - 1)) & ~((2 *(sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long) old_end & (pagesize - 1)) == 0)' failed. 

Код:

Trie::Trie() { 
    word = false; 
    for(int i=0; i<26; i=i+1) { 
     children[i]={NULL}; 
    } 
} 

Trie::~Trie() { 
    for(int i=0; i<26; i=i+1) { 
     delete children[i]; 
    } 
} 

Trie::Trie(const Trie &obj) {} 

void Trie::addWord(string word) { 
    //Subtract 97 to turn character into index 
    //Once word is empty then we need to set the node to true 
    cout << word << " was seen\n"; 
    char first = word.at(0); 
    int index = first - 97; 
    string stringToSend = word.substr(1); 
    Trie * currentNode = children[index]; 
    if(stringToSend.empty()) { 
     this -> word = true; 
     return; 
    } 
    if(currentNode == NULL) { 
     currentNode = new Trie(); 
    } 
    currentNode ->addWord(stringToSend); 
} 

Вот Trie.h

#include <iostream> 
#include <vector> 
using namespace std; 

class Trie { 
    //Data Variables 
    //char value; 
    bool word; 
    Trie* children[26]; 
    public: 
     Trie(); //Constructor 
     Trie(const Trie &obj); 
     ~Trie(); //Deconstructor 
     void addWord(string); 
     bool isWord(string); 
     vector<string> allWordsWithPrefix(string); 
}; 
+0

Отладчик будет отслеживать точную строку, которая вызывает проблему, если вы пройдете через код. Какая строка генерирует эту ошибку? –

+0

Вам не хватает определения 'class Trie'. Таким образом, нет никакой полезной информации о том, что такое «дети». – TBBle

+0

Если вы хотите инициализировать 26 элементов массива с помощью 'children [26] = {NULL};', это совершенно неправильно. Это меняет только 26-й элемент. Чтобы изменить весь массив, используйте цикл или, еще лучше, стандартный контейнер, такой как вектор. – iksemyonov

ответ

1

Trie::children не ду назначено, так что вы не можете delete[]. Указатели в Trie::children могут указывать на динамически выделенные объекты, но сами указатели не были выделены new[]. В вашем деструкторе вам необходимо перебрать children и delete каждый элемент отдельно.

+0

Спасибо, что очистил предупреждение, но это не исправило ошибку, которую я получал. – Tanner

1

Если что-либо, в случае отсутствия полного кода, я бы указать на этой линии:

if(stringToSend.empty()) { 
    children[index] -> word = true; 
} 

Где появляется children[index] быть (опять же, никакого кода, но вывод) указатель на Trie. Таким образом, это разыгрывает неинициализированный указатель и просит об аварии.

Это правильно по сути, проверка должна предшествовать разыменования (в обратном порядке):

if(children[index] == NULL) { 
    children[index] = new Trie(); 
} 
if(stringToSend.empty()) { 
    children[index] -> word = true; 
} 

Edit:

Относно children[26]={NULL}; и convenient array initialization.

Сравнить:

children[26]={nullptr}; 

и

Trie* children[26] = {nullptr}; 

Разница только "одно слово", но это делает разницу. Первая строка изменяет уже объявленный массив, а вторая объявляет и в то же время инициализирует существующий массив, в котором используется новый синтаксис.

Чтобы заполнить массив нулями, используйте простой цикл, как

for(auto& p: children) p = nullptr; 

или, как Джастин Время предложил в вышеупомянутых комментариях,

std::fill(std::begin(children), std::end(children), nullptr); 

где fill() находится в <algorithm> и begin() & end() заявлены во многих стандартных заголовках (например, <iterator>, <vector> или <array>). Это требует от вашего компилятора поддержки C++ 11.

+0

дети [26] = {NULL}; в конечном итоге стал проблемой. Теперь я просто просматриваю и инициализирую каждый элемент до NULL. Спасибо за помощь! – Tanner

+0

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

+0

Правда, хороший улов. Я попытался сосредоточиться на непонимании и критической ошибке ОП. Ваш ответ великолепный! – iksemyonov

1

Декларация children должна выглядеть следующим образом:

array<unique_ptr<Trie>, 26> children; 

Вам может понадобиться #include <array> и #include <memory> для этого. Кроме того, word нужен инициализатор и т.д .:

bool word{}; 

В настоящее время код оставляет word неинициализированный. На самом деле я бы рекомендовал переименовать эту переменную. Имя должно указывать, что это означает (AFAICT указывает на листовой узел); а также избежать столкновения с именем параметра word в вашей функции addWord.

Тогда вам не нужно ничего писать, в частности, о children в конструкторе или деструкторе. На самом деле вам не нужно вообще объявлять деструктора, что хорошо.

addWord функция может выглядеть следующим образом:

void Trie::addWord(string word) 
{ 
    auto index = word.at(0) - 'a'; 

    if (index < 0 || index >= children.size()) 
      return; // or throw exception 

    string stringToSend = word.substr(1); 

    auto &child = children[index]; 

    if (!child) 
     child = make_unique<Trie>(); 

    if (stringToSend.empty()) 
     child->word = true; 

    else 
     child->addWord(stringToSend); 
} 

Я предполагаю, что child->addWord(stringToSend) должен был быть в else, в противном случае вы будете бросать исключение при ударе word.at(0) с пустой строкой.

+0

Я предполагаю, что в 2016 году 'unique_ptr <>' и его помощники стали стандартным способом работы с памятью? В школе у ​​нас не было никого из этого, и у меня были проблемы с пониманием того, где это (не требуется). – iksemyonov

+0

Спасибо за ответ М.М. Это было очень полезно – Tanner

+0

@iksemyonov 'unique_ptr' указывает, что этот указатель« владеет »памятью, на которую указывает. Одно из преимуществ этого заключается в том, что кто-то, читающий код, не должен задумываться о том, кто является владельцем и кто несет ответственность за удаление. Второе преимущество заключается в том, что вы можете следовать правилу Zero в своем коде. Третье преимущество заключается в том, что если ваш код действительно совершает нарушение правила 3, вы получаете ошибку компиляции вместо двойных удалений во время выполнения, как и с необработанными указателями. –

Смежные вопросы