Re[11]: Крашит в дебрях std при работе с ofstream
От: B0FEE664  
Дата: 18.12.18 15:47
Оценка:
Здравствуйте, rg45, Вы писали:

R>И тебя не смущает, что он появился на форуме на 13 лет раньше тебя?


Да какая разница? Код явно низкого качества.
Вот смотрите:

void CDynamicMesh::removeBlock(eing::graphic::world::CBlock *block)
{
    m_blocks.remove(block);
    if(block == m_parentBlock)
    {
        m_parentBlock = m_blocks.empty() ? nullptr : m_blocks.front();
    }
    recalculate();
}

void CDynamicMesh::recalculate()
{
    if(m_blocks.size() && m_parentBlock)
    { ... }
}


О чём говорит проверка if(m_blocks.size() && m_parentBlock) ? Я вижу 4 варианта:
1) m_blocks.size() и m_parentBlock — две независимые переменные
2) Sheridan не пользуется assert'ами
3) оптимизация обращения к первому элементу списка
4) проблемы в другом месте кода

судя по коду в removeBlock пункт 1 отпадает. Значит пункты 2-4 реализуются либо совместно, либо по отдельности. Скорее всего m_parentBlock вообще не нужен — это просто первый элемент из списка.

Теперь смотрим на ~CBlock():

40 CBlock::~CBlock()
41 {
42    { do { eing::CSingleTone::instance()->logger()->start() << "[Debg] {" << eing::CSingleTone::instance()->debug_counter++ << "} " << std::string(std::string("Point" " in file " __FILE__ " at line " __LINE__ " in method ") + std::string(__func__));; eing::CSingleTone::instance()->logger()->stop();; } while(false); };
43    if(m_dynamicMesh)
44    {
45        m_dynamicMesh->removeBlock(this);
46        if(m_dynamicMesh->empty())
47        {
48            delete m_dynamicMesh;
49            m_dynamicMesh = nullptr;
50        }
51    }
52    m_worldBlock->removeGraphicsBlock();
53    m_worldBlock = nullptr;
54    { do { eing::CSingleTone::instance()->logger()->start() << "[Debg] {" << eing::CSingleTone::instance()->debug_counter++ << "} " << std::string(std::string("Point" " in file " __FILE__ " at line " __LINE__ " in method ") + std::string(__func__));; eing::CSingleTone::instance()->logger()->stop();; } while(false); };
55 }


Вас ничего не смущает? Зачем занулять члены класса в деструкторе? Такой приём используют либо новички, либо это хак, который защищает код от падения при обращении к уже разрушенному объекту. (Ну или это статические члены класса, что вряд ли)

Почему m_dynamicMesh — dynamic? Значит где-то есть статик? Т.е. можно предположить, что вызывается delete для переменной не заказанной по new.

Предположим, что m_dynamicMesh — это указатель на CDynamicMesh.
Тогда смотрите:
Если кто-то удаляет объект на который указывает m_dynamicMesh извне деструктора ~CBlock, то

CDynamicMesh::~CDynamicMesh()
{
    EING_LOG_DBG_POINT;
    if(m_dynamicModel) { EING_ST->graphic()->physicsWorld()->RemoveCachedGeometry(m_dynamicModel); } // Это urho3d, не смотрел что там происходит
    delete m_vertexBuffer;
    delete m_indexBuffer;
    delete m_geometry;
    m_podElements.Clear();
    if(m_dynamicModel) { delete m_dynamicModel; } // Это urho3d объект, не мой
    EING_LOG_DBG_POINT;
}


m_blocks никто не чистит и, соответственно, объекты типа CBlock никто не удаляет — это если предположить, что m_blocks имеет тип std::list<CBlock*>. мы получаем кучу ссылок на убитый объект и утечку памяти.
Если же предположить, что m_blocks — это такой список, который удаляет свои элементы при очистке, то получится ещё интереснее: после выполнения ~CDynamicMesh() начнётся выполнение серии деструкторов ~CBlock, которые попытаются удалить себя из списка находящегося в процессе очистки, а последний элемент ещё и удалит CDynamicMesh второй раз. Так или иначе — ничего хорошего.

Из всего этого следует, что объекты типа CDynamicMesh никогда сами не удаляются. Из этого следует, что на объекты CBlock указатели хранятся где-то снаружи CDynamicMesh и там же уничтожаются. Т.е. мы поняли архитектуру: элементы списка владеют своим списком. Они сами себя из списка удаляют, но добавляют их в список внешним образом:

void CDynamicMesh::addBlock(eing::graphic::world::CBlock *block)
{
    m_blocks.push_back(block);
    recalculate();
}


Вы видите, чтобы block->m_dynamicMesh устанавливался в this в этом методе? Не удивлюсь, если окажется, что recalculate() проходит по списку элементов им устанавливает каждому элементу m_dynamicMesh в this.

Не, ну очевидно, что это код опытного хардкорщика презирающего смарт поинтеры и точно знающего где и что удаляется.
И каждый день — без права на ошибку...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.