В настоящее время я работаю над системой отчетов об ошибках на основе исключений для приложений Windows MSVC ++ (9.0) (т. Е. Структуры и типы исключений / наследование, стек вызовов, отчеты об ошибках и ведение журнала и т. Д.).
Теперь у меня вопрос: как правильно сообщить и зарегистрировать ошибку нехватки памяти?
Когда возникает эта ошибка, например, как bad_alloc
, генерируемая операцией new
, может быть недоступно много «функций», в основном касающихся дальнейшего выделения памяти.Обычно я передаю исключение приложению, если оно было брошено в lib, а затем использую окна сообщений и файлы журнала ошибок, чтобы сообщать и регистрировать его.Другой способ (в основном для служб) - использовать журнал событий Windows.
Основная проблема, с которой я сталкиваюсь, - собрать сообщение об ошибке. Чтобы предоставить некоторую информацию об ошибке, я бы хотел определить статическийсообщение об ошибке (может быть строковым литералом, лучше запись в файле сообщения, затем с использованием FormatMessage) и включать некоторую информацию времени выполнения, такую как стек вызовов.
Функции / методы, необходимые для этого, либо
- STL (
std::string, std::stringstream, std::ofstream
) - CRT (
swprintf_s, fwrite
) - или Win32 API (
StackWalk64, MessageBox, FormatMessage, ReportEvent, WriteFile
)
Помимо документирования наMSDN, все они более (Win32) или менее (STL) с закрытым исходным кодом в Windows, поэтому я не знаю, как они ведут себя при проблемах с нехваткой памяти.
Чтобы доказать, что могут быть проблемы, я написал простое маленькое приложение, вызывающее bad_alloc:
int main()
{
InitErrorReporter();
try
{
for(int i = 0; i < 0xFFFFFFFF; i++)
{
for(int j = 0; j < 0xFFFFFFFF; j++)
{
char* p = new char;
}
}
}catch(bad_alloc& e_b)
{
ReportError(e_b);
}
DeinitErrorReporter();
return 0;
}
Работал два экземпляра без присоединенного отладчика (в Release config, VS 2008), но «ничего не произошло»,то есть никаких кодов ошибок из ReportEvent или WriteFile, которые я использовал внутренне в отчете об ошибках.Затем запустили один экземпляр с одним и одним без отладчика и позволили им пытаться сообщать о своих ошибках один за другим, используя точку останова в строке ReportError.Это работало нормально для экземпляра с подключенным отладчиком (правильно сообщал и регистрировал ошибку, даже используя LocalAlloc без проблем)!Но таскман показал странное поведение, когда перед выходом приложения освобождается много памяти, я полагаю, когда выдается исключение.
Учтите, что может быть более одного процесса [edit] и более одного потока [/ edit], потребляющего много памяти, поэтому освобождение предварительно выделенного пространства кучи не является безопасным решением, чтобы избежать нехватки памяти для процесса, который хочет сообщитьошибка.
Заранее спасибо!