Исключение списка STL - PullRequest
       8

Исключение списка STL

2 голосов
/ 31 октября 2009

Я пытался использовать список STL в C ++, и я попал в странное исключение, которое я не в состоянии понять.

Список определяется как 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 и проверенным значением, не ноль ли это, и это именно то, что и должно быть ..

обратная трассировка:

#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(); }

;

Заранее спасибо

Ответы [ 2 ]

4 голосов
/ 31 октября 2009

Ваши конструкторы и операторы присваивания неверны.Когда вы вызываете std::copy, в итераторе назначения уже должно быть достаточно места для размещения всего, что вы копируете в него.Список не будет расти сам по себе.Получаемое сообщение об ошибке указывает на то, что вы перезаписываете некоторую память, и именно это и происходит, когда вы пытаетесь скопировать в недостаточно большой список.(Формально поведение не определено.)

Вы можете использовать std::back_insert_iterator, который является адаптером итератора, который добавляет элементы в базовый контейнер вместо перезаписи текущего местоположения.Создайте его, используя вспомогательную функцию std::back_inserter из заголовка <algorithm>:

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;
}
0 голосов
/ 31 октября 2009

Скорее всего, вы сделали что-то с вашим списком, что произошло до строк кода, которые вы опубликовали. Я бы посоветовал посмотреть во всех местах, где используется m_stats, и дважды проверить его использование. Вы можете опубликовать свои варианты использования m_stats здесь, и мы можем попытаться помочь вам еще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...