【问题标题】:STL list exceptionSTL 列表异常
【发布时间】:2009-10-31 04:10:38
【问题描述】:

我试图在 C++ 中使用 STL 列表,但遇到了一个我无法理解的奇怪异常。

列表定义为list<ASTNode*> m_stats;ASTNode* 是一个类。当我尝试通过调用添加元素时

ASTNode *node = new ASTNode();
m_stats.push_back(node);

它会抛出以下异常:

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x00000004
0x91c20fe7 in std::_List_node_base::hook()

我尝试使用 gdb 进行调试并检查插入的值,它不是 null 吗?它正是它应该是的......

回溯是:

#0  0x91c20fe7 in std::_List_node_base::hook ()
#1  0x0000a9fb in std::list<ASTNode*, std::allocator<ASTNode*> >::_M_insert (this=0x180344, __position={_M_node = 0x0}, __x=@0xbffff094) at stl_list.h:1152
#2  0x0000aa27 in std::list<ASTNode*, std::allocator<ASTNode*> >::push_front (this=0x180344, __x=@0xbffff094) at stl_list.h:743
#3  0x0000aa45 in ASTStatements::addStatement (this=0x180340, stat=0x180410) at ast.h:277

我错过了什么吗?

编辑:添加类源

class ASTStatements : public ASTNode
{
list<ASTNode*> m_stats;

public:
    ASTStatements() {}

    ASTStatements(list<ASTNode*> stats)
    {
        std::copy(stats.begin(), stats.end(), m_stats.begin());
    }

    ASTStatements(const ASTStatements &other)
    {
        std::copy(other.m_stats.begin(), other.m_stats.end(), m_stats.begin());
    }

    ASTStatements &operator= (const ASTStatements &other)
    {
        if (&other != this)
        {
            std::copy(other.m_stats.begin(), other.m_stats.end(), m_stats.begin());
        }
    }

    ASTStatements *clone()
    {
            return new ASTStatements(*this);
        }

        u8 type()
        {
            return 0;
        }

        const char *generateASM()
        {
            list<ASTNode*>::iterator it = m_stats.begin();

            while (it != m_stats.end())
            {
                ((ASTNode*)*it)->generateASM();
                ++it;
            }
        }

        void addStatement(ASTNode *stat)
        {
            m_stats.push_front(stat);
        }

        u8 typeCheck()
        {
            return 0;
        }
};

我在野牛语法文件中使用它来处理多个语句(没有找到更好的方法来处理非终端中的通用项目列表):

statements:
    statement { if ($$ == null) $$ = new ASTStatements(); ((ASTStatements*)$$)->addStatement($1); } statements { $$->generateASM(); }

;

提前致谢

【问题讨论】:

  • 问题不在于您发布的任何代码行。显然,您的 list 在此之前已经损坏了一段时间。
  • 堆栈跟踪与发布的源不对应(push_back vs push_front等)
  • 您的程序没有抛出异常,而是您的操作系统正在通过分段错误使您的程序摆脱困境。

标签: c++ exception list stl


【解决方案1】:

您的构造函数和赋值语句是错误的。当您调用std::copy 时,目标迭代器必须已经有足够的空间来容纳您复制到其中的所有内容。该列表不会自行增长。您收到的错误消息表明您正在覆盖一些内存,这可能正是您尝试复制到不够大的列表时发生的情况。 (形式上,行为是未定义的。)

您可以使用std::back_insert_iterator,它是一个迭代器适配器,可将项目附加到底层容器,而不是覆盖当前位置。使用 &lt;algorithm&gt; 标头中的 std::back_inserter 辅助函数创建一个:

std::copy(stats.begin(), stats.end(), std::back_inserter(m_stats));

不过,更好的是跳过所有复制,让列表自己的构造函数和赋值运算符为您处理,因为它们的设计目的是:

ASTStatements(list<ASTNode*> stats)
  : m_stats(stats)
{ }

ASTStatements& operator=(const ASTStatements& other)
{
  m_stats = other.m_stats;
}

【讨论】:

  • ASTStatements(list&lt;ASTNode*&gt; stats) - 我认为您不想在每次复制时传递这样的列表。 ASTStatements(const list&lt;ASTNode*&gt;&amp; stats) 怎么样?而且,实际上,习惯用法是传递迭代器并将它们作为模板参数:template&lt;typename It&gt; ASTStatements(It begin, It end) : m_stats(begin,end) {}。遵循常用成语有其优点。
【解决方案2】:

您对列表所做的很可能是在您发布的代码行之前发生的。我建议查看所有使用m_stats 的地方,并仔细检查您的使用情况。您可以在此处发布您对m_stats 的使用情况,我们可以尝试为您提供更多帮助。

【讨论】:

    猜你喜欢
    • 2011-09-16
    • 1970-01-01
    • 1970-01-01
    • 2018-09-27
    • 2016-03-25
    • 2020-10-15
    • 2011-08-09
    • 1970-01-01
    • 2011-01-11
    相关资源
    最近更新 更多