C++ 这个错误是什么;test:malloc.c:2388:sysmalloc:Assertion。。。“失败”;
编辑:我已经解决了,把我的新代码放在下面。谢谢你的帮助 我有一个空指针数组,我试图在某个索引处设置一个数组元素,以指向我创建的类的对象,但最终出现以下错误:C++ 这个错误是什么;test:malloc.c:2388:sysmalloc:Assertion。。。“失败”;,c++,pointers,malloc,C++,Pointers,Malloc,编辑:我已经解决了,把我的新代码放在下面。谢谢你的帮助 我有一个空指针数组,我试图在某个索引处设置一个数组元素,以指向我创建的类的对象,但最终出现以下错误: test: malloc.c:2388: sysmalloc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) &&
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(){
字=假;
for(int i=0;iTrie::children
不是动态分配的,因此您不能delete[]
它。Trie::children
中的指针可能指向动态分配的对象,但指针本身没有分配new[]
。在析构函数中,需要分别循环子元素和删除每个元素。如果没有完整的代码,我会指向这一行:
if(stringToSend.empty()) {
children[index] -> word = true;
}
其中children[index]
似乎是指向Trie
的指针(同样,没有代码,只有演绎)。因此这是取消对未初始化指针的引用,并请求崩溃
该检查本身正确,应在取消引用之前进行(相反顺序):
编辑:
关于子项[26]={NULL};
和
比较:
children[26]={nullptr};
及
区别只是“一个字”,但它起了作用。第一行是更改已声明的数组,而第二行是声明并同时初始化正在使用新语法的现有数组
要用零填充数组,请使用简单的循环,如
for(auto& p: children) p = nullptr;
或者,正如Justin Time在上面的评论中所建议的
std::fill(std::begin(children), std::end(children), nullptr);
其中fill()
在
中,而begin()
和end()
在许多标准头中声明(例如
、
或
)。这要求编译器支持C++11。子项的声明应如下所示:
array<unique_ptr<Trie>, 26> children;
当前,您的代码未初始化word
。事实上,我建议重命名此变量。名称应指明其含义(AFAICT它表示叶节点);并且它将避免与addWord
函数中的参数名称word
冲突
然后,您不需要在构造函数或析构函数中编写关于子类的任何特定内容。事实上,您根本不需要声明析构函数,这是一件好事
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);
}
void-Trie::addWord(字符串字)
{
自动索引=word.at(0)-'a';
如果(索引<0 | |索引>=children.size())
return;//或抛出异常
字符串stringToSend=word.substr(1);
auto&child=子项[索引];
如果(!child)
child=使_唯一();
if(stringToSend.empty())
child->word=true;
其他的
child->addWord(stringToSend);
}
我假设child->addWord(stringToSend)
应该位于else
中,否则在点击word.at(0)时会抛出异常
使用空字符串。如果您单步执行代码,调试器将跟踪导致问题的确切行。哪一行生成错误?您缺少类Trie
本身的定义。因此没有关于子类的有用信息。如果您要初始化具有子项[26]={NULL}
,这是完全错误的。这只会更改第26个元素。要更改整个数组,请使用循环,或者更好的是使用vector之类的标准容器。我敢肯定“new”会告诉您堆内存状态已损坏。在该代码中的许多地方,您可能在跟踪随机指针并向其写入内容。iksemyonov,是的,这就是我要做的。你确定我做不到吗?我正在跟踪,谢谢,这清除了一个警告,但没有修复我得到的错误。children[26]={NULL};最终成为了问题所在。我现在只需循环并初始化每个元素为NULL。感谢您的帮助!使用这种方法,另一个问题是析构函数需要在数组上循环删除每个指针,而不是当前的codeTrue,很好的捕获。我试着集中讨论OP的误解和关键错误。您的answer真是太棒了!我想在2016年,unique_ptr
和它的助手已经成为处理记忆的标准方式了?在学校我们没有这些,我很难理解它们在哪里(不是)需要。谢谢您的回复。这非常好helpful@iksemyonovunique\u ptr
表示此指针“拥有”它指向的内存。这样做的一个好处是,阅读代码的人不必开始考虑谁是所有者以及谁负责删除。第二个好处是,您可以遵循第三的好处是,如果你的代码确实犯了三的违规规则,那么你就得到了编译错误,而不是在运行时的双删除,就像你用原始指针一样。很好,读起来。C++似乎是从我的学校时代开始演变的。
for(auto& p: children) p = nullptr;
std::fill(std::begin(children), std::end(children), nullptr);
array<unique_ptr<Trie>, 26> children;
bool word{};
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);
}