нарушение доступа внутри набора записей ADODB Закрыть - PullRequest
0 голосов
/ 23 ноября 2018

Все еще пытаюсь выяснить, что происходит с соединениями ADODB и почему происходит определенный сбой.

Проблема заключалась в том, что в нашем коде произошла утечка памяти:

void getDetailConfig()
{
    m_displayConf = new TestDetailDisplayCfg(); 
}

Эта функция часто вызывается, поэтому базовая утечка памяти.Исправлено это с уникальным указателем

void getDetailConfig()
{
    m_displayConf = std::make_unique<TestDetailDisplayCfg>();
}

Вечеринка, но теперь нарушение доступа стало происходить внутри Recordset15 :: Close.

inline HRESULT Recordset15::Close ( ) {
    HRESULT _hr = raw_Close();
    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
    return _hr;
}

Необработанное исключение в 0x679E653F (msado15.dll) в LaneControl.exe: 0xC000041D: Обнаружено необработанное исключение во время обратного вызова пользователя.

Поэтому правильный вызов всех деструкторов вызвал новую проблему, где-то открыты и закрыты наборы записей.

После отладки выясняется, что getDetailConfig вызывается из двух разных потоков.

Thread1

void updateIconStatus()
{
    getDetailConfig();
}

thread1

Идентификатор резьбы 5bA8

Резьба2

void CVTSDetailDisplay::setCurrentTestIconStatus(int status)
{
    m_CurrentDialog->getDetailConfig();
}

thread2

Идентификатор резьбы 6A4C

Таким образом, эти 2 потока вызывают getDetailConfig, где набор записей закрыт, который был открыт в другом потоке, а объекты COM освобождены, а что нет.

Это проблема, что вы не можете закрыть наборы записей ADO в другом потоке?Это скорее состояние гонки?Что здесь не так на уровне ADODB?

1 Ответ

0 голосов
/ 23 ноября 2018

Я бы подумал, что это состояние гонки.

Если функция getDetailConfig() уже была вызвана ранее, и тогда оба потока вызывают getDetailConfig(), это может привести к тому, что оба потока вызовут деструктор (объекта, который был там раньше) одновременно (std::unique_ptr не является по сути потокобезопасным AFAIK).

Затем необходимо обеспечить критическую секцию для обмена указателями, например, добавив std::mutex m_mutex;как член вашего класса (в идеале на первое место в списке участников, чтобы он оставался действительным дольше, чем m_displayConf член), а затем добавив

void getDetailConfig()
{
    std::unique_lock<std::mutex> lock(m_mutex);
    m_displayConf = std::make_unique<TestDetailDisplayCfg>();
}

, чтобы убедиться, что обмен заблокирован между потоками.

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