gpt4 book ai didi

c++ - 尝试 push_back 到 std::vector 时出现段错误

转载 作者:太空狗 更新时间:2023-10-29 20:54:13 25 4
gpt4 key购买 nike

我有一个 Token类结构如下:

class Token {
public:
void* value;
token_type type; // enum to know which type of data is it storing inside value
unsigned int line;

Token() = default;

Token(void* new_value, token_type new_type):
value(new_value), type(new_type)
{}

~Token() {
//free the memory occupied by the object pointed to by value based on it's type
//this also handles the case of the Token being an instantiation of Statement
}
};

然后是类语句:

class Statement: public Token {
public:
std::vector<Token*>* list;
unsigned int lenght = 0;

Statement() {
list = new std::vector<Token*>;
Token((void*) list, statement);
}
};

基本上,当创建一个声明时,内部 token 知道它持有一个声明,因为有一个特定的token_type。为此输入。内部 token 在其析构函数中清理 vector ,因此它必须在其 value 中有一个指向该 vector 的指针。属性,但我们在语句中也有该指针的拷贝,因此我们不需要从 void* 进行转换至 std::vector<Token>*每一次;

现在,我要做的是:

std::string* value = new std::string("Sample text");
Token* to_be_pushed = new Token((void*) value, string); //the object pointed to by value will be deleted in this Token's destructor

Statement* new_statement = new Statement;

new_statement->list->push_back(to_be_pushed);

delete new_statement; //Token destructor gets called; It knows it's a statement,
//so it knows value is pointing to a std::vector<Token*> object, and it deletes each pointer in that vector and then the vector itself

但是,问题是我在推送 to_be_pushed 的行上遇到了段错误。在 new_statement->list 的末尾.

我试过将那条线分成两部分,我知道问题出在我调用 list->push_back 时, 不是在访问 new_statement->list 时.

这是我从 gdb 得到的回溯:

#0  0xb6e51410 in memmove ()
from /system/lib/libc.so
#1 0x2a0066f8 in std::__copy_move<true, true, std::random_access_iterator_tag>::__copy_m<Token*>
(__first=0x2a0198d0, __last=0x0,
__result=0x2a019908)
at /data/data/com.termux/files/usr/include/bits/stl_algobase.h:378
#2 0x2a006640 in std::__copy_move_a<true, Token**, Token**> (__first=0x2a0198d0, __last=0x0,
__result=0x2a019908)
at /data/data/com.termux/files/usr/include/bits/stl_algobase.h:395
#3 0x2a007070 in std::__copy_move_a2<true, Token**, Token**> (__first=0x2a0198d0, __last=0x0,
__result=0x2a019908)
at /data/data/com.termux/files/usr/include/bits/stl_algobase.h:432
#4 0x2a007010 in std::copy<std::move_iterator<Token**>, Token**> (__first=..., __last=...,
__result=0x2a019908)
at /data/data/com.termux/files/usr/include/bits/stl_algobase.h:464
#5 0x2a006fb0 in std::__uninitialized_copy<true>::__uninit_copy<std::move_iterator<Token**>, Token**> (__first=..., __last=...,
__result=0x2a019908)
at /data/data/com.termux/files/usr/include/bits/stl_uninitialized.h:93
#6 0x2a006f70 in std::uninitialized_copy<std::move_iterator<Token**>, Token**> (__first=...,
__last=..., __result=0x2a019908)
at /data/data/com.termux/files/usr/include/bits/stl_uninitialized.h:123
#7 0x2a006eec in std::__uninitialized_copy_a<std::move_iterator<Token**>, Token**, Token*> (
__first=..., __last=...,
__result=0x2a019908)
at /data/data/com.termux/files/usr/include/bits/stl_uninitialized.h:279
#8 0x2a006dc0 in std::__uninitialized_move_if_noexcept_a<Token**, Token**, std::allocator<Token*> > (__first=0x2a0198d0, __last=0x0,
__result=0x2a019908, __alloc=...)
at /data/data/com.termux/files/usr/include/bits/stl_uninitialized.h:300
#9 0x2a007264 in std::vector<Token*, std::allocator<Token*> >::_M_emplace_back_aux<Token* const&> (this=0x2a019908,
__args=@0x2a0198e8: 0x2a0198d0)
at /data/data/com.termux/files/usr/include/bits/vector.tcc:457
#10 0x2a005b70 in std::vector<Token*, std::allocator<Token*> >::push_back (this=0x2a019908,
__x=@0x2a0198e8: 0x2a0198d0)
at /data/data/com.termux/files/usr/include/bits/stl_vector.h:1049

为什么会这样?我究竟做错了什么?是我发布的代码有问题吗?

最佳答案

Token((void*) list, statement);

您期望这会调用父类(super class)的构造函数。这不会调用构造函数。所有这一切只是构造一个临时对象,然后立即销毁。调用父类(super class)的构造函数的唯一方法是在子类的初始化部分:

 Statement() : Token(...)

但是在您的情况下,您需要在调用父类(super class)的构造函数之前初始化子类,即它的 list 成员。这不容易做到。尽管有很多解决方法,但这确实是此类层次结构的基本设计缺陷的征兆。

你有两个选择:

  1. 重新实现您的类层次结构。您的类(class)设计方式根本上是错误的。设计得当的 C++ 代码永远不需要执行转换为 void * 等技巧。

  2. Statement 的构造函数中手动初始化 Token。使用 Token 的默认构造函数,然后在 Statement 的构造函数体中修复它。

但是,即使您尝试了 #2 方法,您以后也可能会发现其他问题,特别是:您的 Statementviolates the Rule Of Three .这几乎可以肯定会导致许多难以追踪的错误。

这里的正确答案是退后一步,完全重新设计您的类层次结构。摆脱 new 分配以支持正确使用 C++ 库容器也是一个优势。

有很多方法可以重新设计这个类层次结构,如果没有额外的信息,就不可能提出正确的类设计。

关于c++ - 尝试 push_back 到 std::vector 时出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39946001/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com