I'm trying create a vector of objects called Tokens, each of them when constructed takes a pointer to data, the data is then copied to the location provided from malloc inside Token constructor, the destructor then frees that memory.
The problem I have is that in order to add it to a vector a copy of the object is created which then frees that memory and makes it no longer valid for the copy in the vector so when life of the object in the vector ends free tries to free a memory that was already freed.
Is there any way around that without making the vector of Tokens a vector of Token pointers?
Here is a code example:
#include <iostream>
#include <initializer_list>
#include <cstdlib>
#include <cstring>
#include <vector>
namespace alpaca
{
enum class token_type
{
comma,
dollar,
percent,
star,
ampersand,
semicolon,
colon,
at,
open_brace,
close_brace,
open_parenthesis,
close_parenthesis,
arrow,
identifier,
number,
string,
eof,
none,
};
enum class token_modifier
{
is_negative,
is_float
};
struct token
{
public:
template<class T>
static token create(int line, int column, alpaca::token_type type, T literal,
std::initializer_list<alpaca::token_modifier> modifiers = {})
{
return token(line, column, type, (void*)(&literal), sizeof(T), modifiers);
}
template<class T>
T get_literal()
{
return *reinterpret_cast<T*>(_literal);
}
~token();
private:
token(int line, int column, alpaca::token_type type, void* literal_data, size_t literal_type_size,
std::initializer_list<alpaca::token_modifier> modifiers);
int _line;
int _column;
alpaca::token_type _type;
std::vector<alpaca::token_modifier> _modifiers;
void* _literal;
size_t _literal_size;
};
}
alpaca::token::token(int line, int column, alpaca::token_type type, void* literal_data, size_t literal_type_size,
std::initializer_list<alpaca::token_modifier> modifiers) :
_line(line), _column(column), _type(type), _literal_size(literal_type_size)
{
_literal = malloc(literal_type_size);
for (auto modifier : modifiers)
{
_modifiers.push_back(modifier);
}
std::memcpy(_literal, literal_data, literal_type_size);
}
alpaca::token::~token()
{
free(_literal);
}
void f(std::vector<alpaca::token>& tokens)
{
int a = 4;
auto g = alpaca::token::create(0, 0, alpaca::token_type::number, a);
tokens.push_back(g);
}
int main() {
std::vector<alpaca::token> tokens;
f(tokens);
return 0;
}