Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Перехват исключений - настройка компилятора.


Автор: neosapient 3.8.2012, 12:21
Добрый день.

Какие ещё параметры в настройках проекта VC2008 отвечают за обработку исключений?

Делаю dll, которая работает с MySQL через с статически-линкуемую mysqlclient.lib. Начал проводить нагрузочное тестирование - dll стала падать.
Тогда я обернул каждую функцию в try/catch блоки
Код

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
// ... много кода
// долго ожидаем какого то события
// работают циклы, вызываются методы разных классов и функции, например, foo()
// все они обернуты в try/catch блоки
}

void foo(void)
{
  try{
  // что то делаем, например, читаем данные из MySQL
  }
  catch(...){
  // пишем в файл об ошибке
  }
}

Т.е. обернул вообще каждую функцию и метод класса в try/catch.
Но падения продолжались.

Зашел в настройки проекта (у меня VC2008) и установил
Properties: Configuration Properties -> C\C++ -> Code Generation ->Yes With SEH Exceptions (/EHa)

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

Автор: Randajad 3.8.2012, 12:39
Если бы исключения не были включены, то студия бы вас материла за это. Кстати, SEH - это совершенно иные исключения. Вам хватит и /EHs, я думаю(оно по-умолчанию, вроде как, и есть).
Проблема в другом, я думаю. DllMain должна как можно быстрее возвращать управление. В ней нельзя делать много действий и различных системных вызовов. Можно использовать только функции библиотеки kernel32.

Автор: neosapient 3.8.2012, 12:52
При старте запускается дочерний поток, в котором идет основная работа.
При завершении Главной программы, мою dll уведомляют, что пора закрывать дочерний поток, что она и делает.

Системных вызовов не делаю, только опрос и запись данных в MySQL.

Я гадаю, может при статической линковке mysqlclient.lib компилятор не подцепил обработку исключений из этой библиотеки?

Автор: Randajad 3.8.2012, 13:00
Ничего в ней не делайте. Можете даже убрать. Будете спать крепче. Кто дает гарантии, что загружены все нужные DLL, когда вы создаете поток? А MySQL, по-вашему, системных вызовов не делает?
Компилятор умный, зря вы так. mysqlclient.lib - это библиотека на C? Если да, в ней нет исключений.

Добавлено через 3 минуты и 2 секунды
К тому же, создание потоков запрещено в DllMain.

Автор: boostcoder 3.8.2012, 13:08
Цитата(Randajad @  3.8.2012,  13:00 Найти цитируемый пост)
mysqlclient.lib - это библиотека на C?

ага.


Цитата(Randajad @  3.8.2012,  13:00 Найти цитируемый пост)
в ней нет исключений.

возможно речь идет о сегфолтах?

Автор: Randajad 3.8.2012, 13:15
Не-не. Сегфолты там? Я все-таки считаю, что они умные люди и до такого бы не опустились. smile Плюс, она есть для GCC и линупса - а там нету SEH.
В любом случае, все это уже прописано в либе и читается линкером. А /Eh* влияют только на компиляцию того кода, который, собственно, компиляют, а не на код либы.

Автор: bems 3.8.2012, 18:50
Цитата(Randajad @  3.8.2012,  13:00 Найти цитируемый пост)
создание потоков запрещено в DllMain

нет, создание разрешено, но фактическое начало выполнения треда происходит после выхода из DllMain

Автор: bems 3.8.2012, 19:05
Цитата(Randajad @  3.8.2012,  13:15 Найти цитируемый пост)
Сегфолты там? Я все-таки считаю, что они умные люди и до такого бы не опустились
они не обязаны предусматривать ситуацию вызова их функций до выполнения DllMain

Автор: Randajad 3.8.2012, 21:41
Нельзя запускать. Это может потребовать блокировку загрузчика OS, что в свою очередь может вызвать deadlock.

Насчет:
Цитата

они не обязаны предусматривать ситуацию вызова их функций до выполнения DllMain

Не понял глубокой мысли. Я говорил о SEH исключениях и только.

Автор: bems 3.8.2012, 22:21
Цитата(Randajad @  3.8.2012,  21:41 Найти цитируемый пост)
Нельзя запускать. Это может потребовать блокировку загрузчика OS, что в свою очередь может вызвать deadlock.
Можно. Это вызовет попытку свежесозданного потока залочится на упомянутом локе, но это еще не дедлок. В этом сценарии новый тред успешно дожидается критическую секцию когда создавший выходит из дллмейн. А вот когда код в дллмейн пытается дождаться завершения созданного им потока, ну или кого-нить эвента, который должен установить тред когда инициализируется, вот тогда это уже дедлок

Цитата(Randajad @  3.8.2012,  21:41 Найти цитируемый пост)
Не понял глубокой мысли. Я говорил о SEH исключениях и только.

Я тоже говорил именно о них. 
Почему нельзя вызывать никакие апи, кроме kernel32? Потому что нет гарантии что для остальных используемых длл уже вызвана дллмейн. Но это же касается и вообще любых используемых длл, не только вин-апишных. Например авторы mysqlclient в своей длл мейн инициализируют глобальный указатель адресом, выделенным из кучи. В экспортируемых функциях они обращаются к этой памяти по этому указателю. 
Они не обязаны предусматривать вариант что кто-то может вызвать экспорт до того как отработает дллмейн. В этом случае функция пытается разыменовать неинициализированный глобальный указатель и получаем закономерное access violation, которое успешно проходит через границы модулей

Так глубокая мысль более понятна?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)