Обнаружение неправильного использования переменной стека - PullRequest
1 голос
/ 09 мая 2011

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

void Execute ProcessWork
{
    int nRes = 0;
    CFireProcessMessageWork *pProcessMessageWork = new CFireProcessMessageWork();
    // Incorrect use of stack variable
    pProcessMessageWork->m_pStatus = &nRes;
    // Worker Agency
    m_pMessageWorkerAgency->SubmitWork(pProcessMessageWork);
}

Определение CFireProcessMessageWork приводится ниже.Метод DoWork приведенного ниже класса будет выполняться в рабочем потоке.Поскольку переменная nRes используется ненадлежащим образом, мое приложение иногда падает.Я провел почти неделю, чтобы определить причину проблемы.Я пробовал кучу страниц с полными опциями и стека фреймов (/ RTC), чтобы обнаружить проблему.Но приложение упало в месте, не имеющем отношения к проблеме.

Существуют ли какие-либо инструменты, предоставляемые Microsoft для обнаружения проблем такого рода?1011 *

Ответы [ 2 ]

3 голосов
/ 09 мая 2011

Проблема в том, что каждая из этих строк имеет смысл для компилятора.В них нет ничего неправильного , и просто комбинация не очень хороша.Даже тогда потребовалось бы значительное количество дополнительной работы и анализа, чтобы определить, что это неправильное использование.

Рассмотрим, например, что вы можете присоединиться к рабочему потоку в той же функции, и тогда все будетПравильно, если функция не обрабатывала в другом потоке, а просто манипулировала кодом в вызове SubmitWork, это было бы правильно ... и компилятору не обязательно знать о потоков , поэтомуДело в том, что компилятору почти невозможно обнаружить это.

С другой стороны, это то, что должно быть совершенно очевидно для рецензента, поэтому его можно лучше решить, просматривая код.Другими возможными вариантами было бы использование некоторой формы совместного владения ресурсами для обработки ресурсов, что может означать более высокую стоимость:

void Execute ProcessWork {
    std::shared_ptr<int> nRes = std::make_shared<int>( 0 );
    CFireProcessMessageWork *pProcessMessageWork = new CFireProcessMessageWork();
    pProcessMessageWork->m_pStatus = nRes;                   // copies the shared_ptr
        m_pMessageWorkerAgency->SubmitWork(pProcessMessageWork);
}

В этом случае общее владение владением объектом настоимость дополнительного выделения гарантирует, что поток не будет вызывать неопределенное поведение при обновлении состояния.Но хотя это и сделает программу корректной с языковой точки зрения, это все равно может быть нежелательным: статус не будет читаемым вне рабочего потока, поскольку единственной другой ссылкой является снаружи рабочего контроля.

3 голосов
/ 09 мая 2011

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

...