#c #access-violation
#c #нарушение доступа
Вопрос:
Следующие минимальные примеры кода выполняются нормально при обычном завершении (нажатием enter):
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
class SingletonLogClass
{
private:
SingletonLogClass() {}
public:
~SingletonLogClass()
{
LogMessage("~SingletonLogClass()");
}
static SingletonLogClassamp; getInstance(void)
{
static SingletonLogClass inst;
return inst;
}
void LogMessage(string msg)
{
//printf("%sn", msg.c_str());
cout << msg << endl;
}
};
int main(int argc, char* argv[])
{
SingletonLogClass::getInstance().LogMessage("This is a message");
getchar();
return 0;
}
Когда я завершаю программу, закрывая окно консоли, это зависит от реализации LogMessage
функции. Если это реализовано с помощью printf
, все в порядке. Но когда это реализовано с помощью cout
, я получаю нарушение доступа.
Кто-нибудь может это объяснить? Что именно происходит, когда программа завершается закрытием окна консоли? Почему это работает с printf
, но не с cout
?
Я работаю с VC 2010.
Комментарии:
1. Получаю то, о чем вы просите, лично.
Ответ №1:
cout
является глобальным объектом. Ваш одноэлементный экземпляр (определенный как статический в getInstance
статической функции-члене) также является глобальным объектом.
В C вы не можете контролировать порядок построения или уничтожения глобальных объектов. Таким образом, возможно, что cout
объект будет уничтожен раньше вашего SingletonLogClass
. Поскольку ваш деструктор SingletonLogClass
что-то регистрирует, он больше не может использовать cout
(тогда как printf
все в порядке).
Разница в поведении при обычном завершении программы (нажатие enter) и, таким образом, выходе из main
функции и при внезапном завершении программы путем закрытия командной строки обусловлена порядком уничтожения глобальных файлов. Вы не можете контролировать порядок уничтожения глобальных объектов.
Комментарии:
1. @Дидье Троссе: Мой 1, это точно.
2. Хорошо, пока это имеет смысл. Но почему это работает, когда программа завершается нормально? Задействован ли другой механизм или это чистая удача, что в этом случае мой
SingletonLogClass
уничтожается первым?3. Каким образом одноэлементный экземпляр является глобальным объектом?
4.@Nawaz: Экземпляр singleton является
function local
static
объектом. Как таковое, оно находится в глобальной области данных (в отличие от стека и кучи).5. @Didier: Но каким образом это глобальный экземпляр? Если длительность объекта равна продолжительности программы, это не означает, что его глобальный объект.