Нарушение доступа при необычном завершении программы (C )

#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: Но каким образом это глобальный экземпляр? Если длительность объекта равна продолжительности программы, это не означает, что его глобальный объект.