c++ - std::vector.push_back() throwing badalloc exception -


i started writing lexer, , made following file test far working okay:

main.cpp

#include <iostream> #include "lexer.h" #include "token.h"  int main(void) {     std::string str(""); // i'll use test expressions     lexer lexer(str);     std::vector<token> tokens = lexer.lex();     for(auto = tokens.begin(); != tokens.end(); ++it)     {         std::string str;         switch(it->type)         {         case tokentype::_eof:             str = "eof";             break;         case tokentype::error:             str = "error";             break;         case tokentype::semicolon:             str = "semicolon";             break;         case tokentype::plus:             str = "plus";             break;         case tokentype::less_than:             str = "less_than";             break;         case tokentype::greater_than:             str = "greater_than";             break;         case tokentype::int:             str = "int";             break;         case tokentype::id:             str = "id";             break;         case tokentype::whitespace:             str = "whitespace";             break;         default:             str = "<unknown token>";         }         std::cout << str << ", detail='" << it->detail << "'" << std::endl;     }     return 0; } 

the line lexer.lex() throws exception. looking in lexer.h:

std::vector<token> lexer::lex(void) {     // reset input pointer     inputptr = 0;     updatecurrentchar();     // read tokens until eof     std::vector<token> tokens;     token *token = nullptr;         {         token = getnext();         tokens.push_back(*token);     } while(token->type != tokentype::_eof);     return tokens; } 

the line tokens.push_back(*token) throwing exception:

exception details

i tried looking @ info on push_back() here, , saw that:

if reallocation happens, storage allocated using container's allocator, may throw exceptions on failure (for default allocator, bad_alloc thrown if allocation request not succeed).

this seems problem, don't understand why allocation request wouldn't succeed.

for completeness, here files:

token.h

#pragma once #include <string>  enum class tokentype {     _eof,     error,     equals,     semicolon,     plus,     less_than,     greater_than,     int,     id,     whitespace };  struct token {     tokentype type;     std::string detail; }; 

lexer.h

#pragma once #include <string> #include <vector> #include "token.h"  class lexer { public:     lexer(std::string);     ~lexer(void);     std::vector<token> lex(void); private:     token* getnext(void);     void updatecurrentchar(void);     void increment(void);     bool matchcurrent(char);     bool iswhitespace(char) const;     bool isdigit(char) const;     bool isletter(char) const;     bool islowercaseletter(char) const;     bool isuppercaseletter(char) const;     std::string readwhitespace(void);     std::string readint(void);     std::string readid(void);     std::string input;     int inputptr;     char currentchar;     const char eof_char; }; 

lexer.cpp

#include "lexer.h"  lexer::lexer(std::string _input)     : input(_input), eof_char(-1) {  }  lexer::~lexer(void) { }  std::vector<token> lexer::lex(void) {     // reset input pointer     inputptr = 0;     updatecurrentchar();     // read tokens until eof     std::vector<token> tokens;     token *token = nullptr;         {         token = getnext();         tokens.push_back(*token);     } while(token->type != tokentype::_eof);     return tokens; }  void lexer::updatecurrentchar(void) {     currentchar = inputptr < input.length()         ? input[inputptr]         : eof_char; }  void lexer::increment(void) {     inputptr++;     updatecurrentchar(); }  bool lexer::matchcurrent(char tomatch) {     if(tomatch == currentchar)     {         increment();         return true;     }     return false; }  token* lexer::getnext(void) {     token token;     if(iswhitespace(currentchar))     {         token.type = tokentype::whitespace;         token.detail = readwhitespace();         return &token;     }     if(isdigit(currentchar))     {         token.type = tokentype::int;         token.detail = readint();         return &token;     }     if(isletter(currentchar))     {         token.type = tokentype::id;         token.detail = readid();         return &token;     }     if(currentchar == eof_char)     {         token.type = tokentype::_eof;         return &token;     }     switch(currentchar)     {     case ';':         token.type = tokentype::semicolon;     case '=':         token.type = tokentype::equals;     case '<':         token.type = tokentype::less_than;     case '>':         token.type = tokentype::greater_than;     case '+':         token.type = tokentype::plus;     default:         token.type = tokentype::error;         token.detail = currentchar;     }     increment();     return &token; }  std::string lexer::readwhitespace(void) {     std::string ws;     while(iswhitespace(currentchar))     {         ws += currentchar;         increment();     }     return ws; }  std::string lexer::readint(void) {     std::string ws;     while(isdigit(currentchar))     {         ws += currentchar;         increment();     }     return ws; }  std::string lexer::readid(void) {     std::string ws;     while(iswhitespace(currentchar))     {         ws += currentchar;         increment();     }     return ws; }  bool lexer::isdigit(char c) const {     return c >= '0' && c <= '9'; }  bool lexer::isletter(char c) const {     return islowercaseletter(c)         || isuppercaseletter(c); }  bool lexer::islowercaseletter(char c) const {     return c >= 'a' && c <= 'z'; }  bool lexer::isuppercaseletter(char c) const {     return c >= 'a' && c <= 'z'; }  bool lexer::iswhitespace(char c) const {     switch(c)     {     case ' ':     case '\n':     case '\t':     case '\r':         return true;     default:         return false;     } } 

the problem in getnext return pointer local variable. remember when function returns local variables destructed , pointer points destructed object. or, since local variables on stack , stack reused between function calls, can point different. result of dereferencing invalid pointer leads undefined behavior, , it's common undefined behavior cause crashes, may seem work data screwed up.

the obvious solution of course return copy of object, i.e. don't use pointers (which tip in general).


Comments

Popular posts from this blog

css - Which browser returns the correct result for getBoundingClientRect of an SVG element? -

gcc - Calling fftR4() in c from assembly -

.htaccess - Matching full URL in RewriteCond -