编辑:我已经解决了问题,并将我的新代码放在下面。感谢您的帮助!
我有一个空指针数组,我试图在某个索引处设置一个数组元素,指向我创建的类的对象,但我最终得到了这个错误:
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 :(得分:1)
Trie::children
未动态分配,因此您无法delete[]
。 Trie::children
中的指针可能指向动态分配的对象,但指针本身未分配new[]
。在析构函数中,您需要单独遍历children
和delete
每个元素。
答案 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)
时会抛出异常。