Как обеспечить защиту от нехватки памяти с отключенными исключениями на С++ (VS2010)?

Я работаю над критичной динамически связанной библиотекой (DLL), которая также должна иметь относительно небольшой размер двоичного файла. Поскольку он явно не бросает никаких исключений, я бы вообще хотел отключить поддержку исключений. Однако есть одно исключение (каламбур непреднамеренно): когда заканчивается память (OOM), я должен сообщить код ошибки в приложение, чтобы он мог обработать вещи изящно. База кода слишком велика, чтобы проверять каждое распределение отдельно и распространять ошибку и содержит внешний код, который я не должен касаться. Поэтому я хотел бы перехватывать исключения OOM в моих экспортированных DLL-функциях.

Быстрый тест показывает, что при отключении исключений С++ в Visual С++ 2010 (т.е. флаги нет /EHa,/EHsc или/EHs) он все же переходит к блоку catch (std:: bad_alloc &) при распределении слишком большого объема памяти.

Итак, он работает по своему желанию. Тем не менее, я получаю следующее предупреждение уровня 1: "Используется обработчик исключений C4530: С++, но размытие семантики не разрешено. Укажите /EHsc ". MSDN говорит, что "объект с автоматическим хранилищем в кадре, между функцией, выполняющей бросок, и функцией, улавливающей бросок, не будет уничтожен".

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

В DLL используются отдельный пул памяти? И если да, могу ли я очистить его, не требуя приложения для выгрузки DLL? Я могу легко заставить мою библиотеку игнорировать дальнейшие (экспортированные) вызовы функций, пока приложение не выполнит повторную инициализацию.

Спасибо за ваш совет.

Ответ 1

Несколько предварительных результатов:

Я не знаю, включено ли исключение без обработки исключений, это поведение undefined или нет по стандарту, но вы, конечно же, не собираетесь получать вызовы разворачивания/деструктора сокетов из ваших объектов в стеке.

Если вы пишете код стиля C++, используя RAII для мьютексов, файлов, памяти и т.д., это очень плохое.

Далее, и если ваш код по существу является кодом стиля C:

1) Если вы статически ссылаетесь на библиотеку времени выполнения C, ваша DLL не будет делиться кучей с вашим основным приложением. Разгрузка DLL должна освобождать пропущенную память, но опять же, заботиться о других ресурсах.

2) Если вы динамически связываетесь с временем выполнения C (довольно часто), вы делитесь кучей. Вам нужно будет вручную освободить любую память, выделенную из DLL.

Если я слишком сильно обманывал проблемы с DLL-границей, я бы рекомендовал быстрый бенчмаркинг, чтобы узнать, за что вы платите, в том, что касается исключения исключений. В зависимости от вашей платформы и компилятора неиспользуемые исключения могут иметь весьма незначительное влияние на производительность.