I have a Token
class which is structured as follows:
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
}
};
Then there's the class Statement:
class Statement: public Token {
public:
std::vector<Token*>* list;
unsigned int lenght = 0;
Statement() {
list = new std::vector<Token*>;
Token((void*) list, statement);
}
};
Basically, when creating a Statement, the inner Token knows it's holding a statement because there is a specific token_type
type for that. The inner Token does the cleanup of the vector in its destructor so it has to have a pointer to that vector in its value
attribute, but we also have a copy of that pointer in the Statement so we don't need to do the cast from void*
to std::vector<Token>*
each time;
Now, what I am trying to do is this:
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
The problem, however, is I am getting a Segmentation fault error on the line where I push to_be_pushed
at the end of new_statement->list
.
I've tried breaking that line in two pieces, and I know the problem is when I am calling list->push_back
, not when accessing new_statement->list
.
Here's the backtrace I got from 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
Why is this happening? What am I doing wrong? Is it the code I've posted fault?