7

I am not sure if this is the right forum of this question, but I will try here since this question about the c++ language. The problem:

I use one global variable in my code which is a graphics object. The thing is that when I shut down the program I tried to delete all the created objects (in a function called close, since I wanted to finish some processes from an C API as well). However, when I deleted that global graphics object I got a memory access violation error at the end of main. The reason for this was that the destructor was called again when main ended. This was something that I was not aware of. This led me to the for this program completely irrelevant (since I still wanted to keep the variable until the GUI closed), but for c++ programming really relevant question; Is it impossible to destroy a global c++ object before the end of main?

However, I read this

Static: Objects declared in global or namespace scope (§6.3.4) and statics declared in func- tions (§12.1.8) or classes (§16.2.12) are created and initialized once (only) and ‘‘live’’ until the program terminates (§15.4.3). Such objects are called static objects. A static object has the same address throughout the life of a program execution. Static objects can cause serious problems in a multi-threaded program because they are shared among all threads and typically require locking to avoid data races (§5.3.1, §42.3)

However, though versions of this text appear all over on the internet my question is not completely answered by this explanation. Though it may be implied, since global variables always seem to be static it would be nice to have a straight out answer.

6
  • 2
    If it is declared by smart pointer you should reset() it Dec 5, 2014 at 16:39
  • @ratchetfreak I see, so the only way to be able to destroy a global object before the end of main is to use a pointer? I actually accesses the object with its value since the object itself is not that big. The object mostly contains pointers, so I guess that I did not think about declaring a pointer.
    – patrik
    Dec 5, 2014 at 16:55
  • 2
    or create a dispose method and make sure that after disposing the destructor still works Dec 5, 2014 at 16:57
  • @ratchetfreak Ok, for this program I already have a method that can remove unwanted content for objects of that class. But then it is actually true then that all global variables are always destroyed at the end of main and that it is not possible to destroy them earlier unless they are accessed with a pointer?
    – patrik
    Dec 5, 2014 at 17:02
  • Plain fact is, you should not be using mutable global variables.
    – DeadMG
    Dec 6, 2014 at 17:51

2 Answers 2

10

However, though versions of this text appear all over on the internet my question is not completely answered by this explanation. Though it may be implied, since global variables always seem to be static it would be nice to have a straight out answer.

If you didn't explicitly create it, you don't need to explicitly destroy it. Let's just remove some of the words from your standard quote:

Static: Objects declared in global or namespace scope (§6.3.4) ... are created and initialized once (only) and ‘‘live’’ until the program terminates (§15.4.3). Such objects are called static objects.

So, if you declare an object with global or namespace scope, it is static, and its lifetime is roughly the program lifetime.


By analogy, consider normally-scoped local variables:

void foo() {
    std::string s;
    // code
}

now there is no way to destroy s without exiting its enclosing scope. If you explicitly destroy it in-place, the destructor will still be called again when the scope exits.

Now, consider global and namespace scope to be the top-level scope of your program. You enter this scope before main (which is nested inside the global scope) and exit it after leaving main. This top-level scope lives exactly as long as the program, and you're no more able to destroy the its objects early than you are objects in any other scope.


There is some subtlety about exactly when the constructor gets called (generally before main starts, with a fudge to allow dynamically-loaded libraries without having to talk about platform specifics), when the destructor gets called (relative to exit handlers, say), and the relative ordering of these for different statics (not well-defined, so don't make global initialization or destruction depend on other globals).


Of course, if you want the object to be global for convenience, you can still choose to have explicit setup/cleanup calls instead of using the ctor/dtor for this.

2
  • Ok, I see. I guess that this is a thought through completely. Anyway, I would probably not have figured this out until a long time forward, since I had not done it yet. So thanks!
    – patrik
    Dec 5, 2014 at 17:20
  • −1 because you did not simply recommend a non-global.
    – DeadMG
    Dec 6, 2014 at 17:59
7

This is a simple C++ rule: objects that are more complex that a simple integer, pointer, etc (not a native type) have constructors and destructors. When an instance of such object is declared by value inside a scope, its constructor gets automatically called. When the scope it was declared is exited, the destructor gets automatically called. So take this example:

// Constructor gets called now, which is before 'main()' 
// enters for a global object like this one.
GraphicsObject graphics;

int main()
{
    // Do stuff with 'graphics'
    // ...

} // When we get here, at the end of main, the destructor of 'graphics' is called.

There's no way do change this behaviour, but you can work around it if you need more control over the lifetime of an object. One way is to use pointers. In the following example, I'm going to use a raw pointer for simplicity. You should not adopt this approach though. Always prefer a smart pointer for that.

// Allocated dynamically with 'new'. Constructor still called here, before 'main()' enters. 
// Destructor will not be called until you 'delete' it yourself.
GraphicsObject * graphics = new GraphicsObject;

int main()
{
    // Do stuff with 'graphics'
    // ...

    // 'graphics' destructor only gets called now because we have explicitly
    // deleted it. If we didn't delete the dynamic object, the destructor
    // would never be called. Not deleting would qualify as a "memory leak", BTW.
    delete graphics;
}

Using a pointer, instead of a declaration by value, is the default way of extending the lifetime of an object beyond its scope. In your particular case, however, I suspect the problem could be resolved in a simpler way by introducing a cleanup() method in your graphics object that you call at the end of main(). Make sure that cleanup() frees all associated resources but leaves the object in a state where the destructor can still function when called automatically at the end of main().

Also, it seems that you are trying to implementing the Singleton Pattern, which can be implemented in several different ways. Do an internet search about it and you might find other singleton setups that better fit your needs.

5
  • −1 for not simply recommending a non-global.
    – DeadMG
    Dec 6, 2014 at 17:58
  • 4
    @DeadMG, globals are a tool available in the language, and their use is legitimate in some cases. We have plenty of languages out there to choose from that don't allow globals if you can't stand the concept...
    – glampert
    Dec 6, 2014 at 18:03
  • @DeadMG, you don't have to take my word for it: youtu.be/jK1_3RbEwLE?t=5m55s
    – glampert
    Dec 6, 2014 at 18:14
  • 1
    I like the explanation, but the other answer was good as well and came first. Still I think it rude to not give any notification or credit, so despite the non comment rule I send this. +1 for a good answer and thanks :)
    – patrik
    Dec 8, 2014 at 20:58
  • 1
    @patrik, not problems. The other answer is great, I just wanted to expand on it a little bit further. Thanks!
    – glampert
    Dec 8, 2014 at 21:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.