std :: vector.push_back()抛出badalloc异常

伯蒂·惠恩

我开始编写词法分析器,并制作了以下文件来测试到目前为止所有内容是否正常运行:

Main.cpp

#include <iostream>
#include "Lexer.h"
#include "Token.h"

int main(void)
{
    std::string str(""); // I'll use this to test expressions
    Lexer lexer(str);
    std::vector<Token> tokens = lexer.lex();
    for(auto it = tokens.begin(); it != 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;
}

lexer.lex()行引发异常。寻找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;
    do
    {
        token = getNext();
        tokens.push_back(*token);
    } while(token->type != TokenType::_EOF);
    return tokens;
}

该行tokens.push_back(*token)引发异常:

例外详情

我尝试查看push_back() 此处的信息,并看到了:

如果发生重新分配,则使用容器的分配器分配存储,这可能在失败时引发异常(对于默认分配器,如果分配请求未成功,则抛出bad_alloc)。

这似乎是我的问题,但是我不明白为什么分配请求不会成功。

为了完整起见,以下是所有文件:

令牌

#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;
    do
    {
        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;
    }
}
一些程序员哥们

问题在于您在getNext返回指向局部变量的指针。请记住,当函数返回时,所有局部变量都被破坏,因此指针现在指向一个被破坏的对象。或者,由于局部变量在堆栈上,并且堆栈在函数调用之间被重用,因此它现在可以指向完全不同的对象。然后,您取消引用现在无效的指针的结果将导致未定义的行为,并且未定义的行为会导致崩溃是很常见的,但它似乎可以工作,但数据已被完全破坏。

显而易见的解决方案当然是返回对象的副本,即不要使用指针(通常这是一个很好的技巧)。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

std :: vector :: push_back的成本是成功还是无效?

来自分类Dev

MSVC中std :: vector :: push_back的实现

来自分类Dev

std :: vector函数push_back中的奇怪段错误

来自分类Dev

push_back期间std :: vector分段错误

来自分类Dev

std :: vector中push_back函数的奇怪语法

来自分类Dev

关于`std :: vector :: push_back`的小数的选择

来自分类Dev

线程安全性std :: vector push_back并保留

来自分类Dev

MSVC中std :: vector :: push_back的实现

来自分类Dev

OpenCV点的std :: vector,没有push_back方法

来自分类Dev

std::vector<>::push_back 导致 Arduino 链接错误

来自分类Dev

想要简化我的 std::vector push_back 用法

来自分类Dev

std :: vector <std :: vector <int >> push_back导致堆缓冲区溢出

来自分类Dev

调用std :: vector :: push_back()会更改vector中的先前元素吗?

来自分类Dev

调用std :: vector :: push_back()会更改vector中的先前元素吗?

来自分类Dev

在std :: vector push_back()和std :: map运算符中使用&&作为参数[]

来自分类Dev

使用push_back时,std :: unique_ptr是否已移入std :: vector?

来自分类Dev

std :: vector <std :: unique_ptr <>> :: push_back()的正确语法是什么?

来自分类Dev

std vector push_back':2个重载没有针对“ this”指针错误的合法转换

来自分类Dev

当push_back新元素添加到std :: vector时,C ++参考更改

来自分类Dev

为什么std :: vector :: push_back需要赋值运算符

来自分类Dev

C ++ std :: vector可以同时处理来自多线程的push_back吗?

来自分类Dev

AddressSanitizer将std :: vector <T> :: push_back标识为释放后使用堆错误的原因

来自分类Dev

将指针数组推入std :: vector中,避免使用push_back复制对象

来自分类Dev

std :: vector的push_back()导致奇怪的编译时错误消息

来自分类Dev

C ++ std :: vector可以同时处理来自多线程的push_back吗?

来自分类Dev

为什么使用虚拟析构函数进行std :: vector :: push_back segfaults?

来自分类Dev

OpenMP 并行区域中的 std::vector push_back 会导致错误共享吗?

来自分类Dev

std :: vector.push_back()C ++

来自分类Dev

为什么要在std :: vector :: push_back(T object)方法中构造对象时调用析构函数?

Related 相关文章

  1. 1

    std :: vector :: push_back的成本是成功还是无效?

  2. 2

    MSVC中std :: vector :: push_back的实现

  3. 3

    std :: vector函数push_back中的奇怪段错误

  4. 4

    push_back期间std :: vector分段错误

  5. 5

    std :: vector中push_back函数的奇怪语法

  6. 6

    关于`std :: vector :: push_back`的小数的选择

  7. 7

    线程安全性std :: vector push_back并保留

  8. 8

    MSVC中std :: vector :: push_back的实现

  9. 9

    OpenCV点的std :: vector,没有push_back方法

  10. 10

    std::vector<>::push_back 导致 Arduino 链接错误

  11. 11

    想要简化我的 std::vector push_back 用法

  12. 12

    std :: vector <std :: vector <int >> push_back导致堆缓冲区溢出

  13. 13

    调用std :: vector :: push_back()会更改vector中的先前元素吗?

  14. 14

    调用std :: vector :: push_back()会更改vector中的先前元素吗?

  15. 15

    在std :: vector push_back()和std :: map运算符中使用&&作为参数[]

  16. 16

    使用push_back时,std :: unique_ptr是否已移入std :: vector?

  17. 17

    std :: vector <std :: unique_ptr <>> :: push_back()的正确语法是什么?

  18. 18

    std vector push_back':2个重载没有针对“ this”指针错误的合法转换

  19. 19

    当push_back新元素添加到std :: vector时,C ++参考更改

  20. 20

    为什么std :: vector :: push_back需要赋值运算符

  21. 21

    C ++ std :: vector可以同时处理来自多线程的push_back吗?

  22. 22

    AddressSanitizer将std :: vector <T> :: push_back标识为释放后使用堆错误的原因

  23. 23

    将指针数组推入std :: vector中,避免使用push_back复制对象

  24. 24

    std :: vector的push_back()导致奇怪的编译时错误消息

  25. 25

    C ++ std :: vector可以同时处理来自多线程的push_back吗?

  26. 26

    为什么使用虚拟析构函数进行std :: vector :: push_back segfaults?

  27. 27

    OpenMP 并行区域中的 std::vector push_back 会导致错误共享吗?

  28. 28

    std :: vector.push_back()C ++

  29. 29

    为什么要在std :: vector :: push_back(T object)方法中构造对象时调用析构函数?

热门标签

归档