这是什么错误"测试:malloc.c:2388:sysmalloc:断言...失败"

时间:2016-02-05 03:54:59

标签: c++ pointers malloc

编辑:我已经解决了问题,并将我的新代码放在下面。感谢您的帮助!

我有一个空指针数组,我试图在某个索引处设置一个数组元素,指向我创建的类的对象,但我最终得到了这个错误:

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

3 个答案:

答案 0 :(得分:1)

Trie::children未动态分配,因此您无法delete[]Trie::children中的指针可能指向动态分配的对象,但指针本身未分配new[]。在析构函数中,您需要单独遍历childrendelete每个元素。

答案 1 :(得分: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;
}

编辑:

关于children[26]={NULL};convenient array initialization

比较

children[26]={nullptr};

Trie* children[26] = {nullptr};

差异只是&#34;一个词&#34;,但它有所不同。第一行是更改已经声明的数组,而第二行是声明并同时初始化现有数组,其中使用了新语法。

要用零填充数组,请使用像

这样的简单循环
for(auto& p: children) p = nullptr;

或者,正如Justin Time在上面的评论中所建议的那样,

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

fill()位于<algorithm>begin()&amp; end()在许多标准标头中声明(例如<iterator><vector><array>)。这需要您的编译器支持C ++ 11。

答案 2 :(得分: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)时会抛出异常。