Я работаю над динамически связанной библиотекой (DLL), критичной к производительности, которая также должна иметь относительно небольшой размер двоичного файла. Поскольку он явно не генерирует никаких исключений, я бы хотел вообще отключить поддержку исключений. Тем не менее, есть одно исключение (каламбур непреднамеренный): при нехватке памяти (OOM) я должен сообщить приложению код ошибки, чтобы у него была возможность изящно обрабатывать вещи. База кода слишком велика, чтобы проверять каждое выделение по отдельности и распространять ошибку, и содержит внешний код, который я не должен касаться. Поэтому я хотел бы отлавливать исключения OOM в экспортированных функциях моей DLL.
Быстрый тест показывает, что при отключении исключений C ++ в Visual C ++ 2010 (т. Е. Флаги no / EHa, / EHsc или / EHs) он все равно переходит на улов (std :: bad_alloc&) блокировать при выделении слишком большого объема памяти.
Так что, похоже, работает как хотелось бы. Однако я получаю следующее предупреждение уровня 1: «C4530: обработчик исключений C ++ используется, но семантика раскрутки не включена. Укажите / EHsc». MSDN говорит, что «объект с автоматическим хранением в кадре, между функцией, выполняющей бросок, и функцией, выполняющей бросок, не будет уничтожен».
Что бы я здесь потерял? Можно оставить вещи в неопределенном состоянии, если все, что было создано с помощью библиотеки, может быть удалено, и приложение может запуститься снова (если оно того пожелает). Существует ли большой риск утечки памяти, которую невозможно восстановить?
Используют ли библиотеки DLL отдельный пул памяти? И если так, могу ли я удалить его, не требуя, чтобы приложение выгружало DLL? Я могу легко заставить мою библиотеку игнорировать любые дальнейшие (экспортированные) вызовы функций, пока приложение не выполнит повторную инициализацию.
Спасибо за совет.
Несколько предварительных экзаменов:
Я не знаю, является ли выбрасывание исключения без включенной обработки исключений стандартным поведением или нет, но вы, конечно, не будете получать вызовы разматывания / разрушения стека от ваших объектов в стеке.
Если вы пишете код в стиле C ++ с использованием RAII для мьютексов, файлов, памяти и т. Д., Это очень плохо.
Двигаясь дальше, и предположим, что ваш код по сути является кодом в стиле C:
1) Если вы статически связываетесь с библиотекой времени выполнения C, ваша DLL не будет использовать общую кучу для вашего основного приложения. Выгрузка DLL должна освободить утечку памяти — но, опять же, позаботьтесь о других ресурсах.
2) Если вы динамически связываетесь со средой выполнения C (довольно часто), то вы разделяете кучу. У вас должен быть способ вручную освободить любую память, выделенную из DLL.
Если бы я слишком много занимался проблемами с границами DLL, я бы порекомендовал быстрый бенчмаркинг, чтобы увидеть, за что вы платите с точки зрения оставления включенных исключений. В зависимости от вашей платформы и компилятора неисключенные исключения могут оказывать весьма незначительное влияние на производительность.
Других решений пока нет …