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;i
Trie::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@iksemyonov
unique\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);
}