19

Is it a good practice to declare a vector as global in C++?

This is what I did.

#include <vector>
std::vector<int> vec;

My program compiles successfully, but I am not sure whether this could lead to a runtime error under certain circumstances. According to my understanding, the memory for a global variable will be allocated at compile time, and the compiler may reserve a limited amount of memory to which this vector can expand. Upon hitting this limit, what is being written can eat into the memory used by another variable.

Please advise.

trincot
  • 317,000
  • 35
  • 244
  • 286
cpp_noname
  • 2,031
  • 3
  • 17
  • 30
  • 7
    It's not generally good practise to declare anything as a global variable. – David Heffernan Sep 26 '11 at 15:39
  • is it possible to re initialized all elements of global array or vector with `0` in main function? (without using for loop/ ) I am searching for an efficient or direct way. – Ankit Mishra Jul 10 '20 at 05:06

6 Answers6

13

My program compiles successfully, but I am not sure whether this could lead to a runtime error under certain circumstances.

This is safe to do; the storage for the vec variable will be allocated statically and its default constructor will be called at some point (exactly when within the context of your entire program is not strictly defined, as order of initialization across translation units is not strictly defined).

and the compiler may reserve a limited amount of memory to which this vector can expand. Upon hitting this limit, what is being written can eat into the memory used by another variable.

The vector itself allocates its storage on the heap, so there will be no limitations imposed upon its expansion that would be different if you instantiated the vector as a local variable: you're basically going to be limited by the amount of memory you can contiguously allocate at the points in time the vector needs to reallocate its internal storage.

All of that said, while this is safe to do so, it isn't necessarily good practice; it falls into the domain of every other global variable or globally-accessible bit of storage, which can be a bit of a contentious subject. Generally, I would advise that it is preferable to avoid global variable as a rule. While it may be acceptable in some cases, the global access runs counter to your ability to control the access to the variable and enforce invariants on it and the state it controls or implies. This can lead to difficult-to-maintain systems as a codebase scales because those access paths are not clearly spelled out.

  • But what if all you want is an array of STRINGTABLE resource ID values? For use elsewhere is multiple parts of the software? In my case I wanted to add it inside a namespace ... – Andrew Truckle May 10 '22 at 11:52
6

According to my understanding, the memory for a global variable will be allocated at compile time, and the compiler may reserve a limited amount of memory to which this vector can expand.

This is wrong understanding.

Memory is not allocated at compile time. Memory is allocated at the program startup, and then during the program, depending on the storage types of variables. And when the program shutdowns, all the memory used by it returns to the OS, no matter what.

Upon hitting this limit, what is being written can eat into the memory used by another variable.

No. An object of std::vector<int> can never eat memory used by another variable(s).

Now coming back to your main question,

Is it a good practice to declare a vector as global in C++?

No. Avoid global variables, irrespective of their types.

Nawaz
  • 353,942
  • 115
  • 666
  • 851
5

Only the space for the vector metadata will be allocated in the area for global variables. The vector contents will still be dynamically allocated (constructors and destructors run normally for global variables).

It's the same situation for an automatic vector variable, like:

int main(void)
{
    std::vector<int> v;
    return 0;
}

There's a limit to the stack space available for automatic variables, but the vector contents won't use this space, only a handful of pointers and counters.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • 1
    Regarding limits to stack space (http://stackoverflow.com/questions/1825964/c-c-maximum-stack-size-of-program) mind you I'm surprised it isn't normal to allocate extra stack pages on demand using page faults a la virtual memory swapping -- the stack and heap could conceivably grow together from opposite extremes of the virtual address space – spraff Sep 26 '11 at 15:45
  • 1
    @spraff: What the stack limits are is totally beside the point -- vector contents are not stored contiguously with the vector members, they are stored in a dynamically allocated area. Also, once upon a time stack and heap did grow toward each other. Then multithreading got invented, and there arose a need for multiple stacks inside a single address space. – Ben Voigt Sep 26 '11 at 15:47
4

Global variables in general are bad practice. They won't "eat" into memory of another variable as you say, however, it's very easy for you as the programmer to screw something up. For example, everything in the program has access to this vector and so everything can access and modify it. You may or may not want this, but more than likely, you don't want this.

As for memory allocation, objects added to the vector are still added on runtime (because they don't exist on compile time!). Memory is also never allocated at compile time. Your program has the signature in it to allocate this memory at RUN time. Think about that...if the program allocated memory at compile time, you wouldn't really be able to run them on other machines would you? The memory would be allocated on YOUR machine, but not on other machines. Hence, memory must be allocated on run time.

MGZero
  • 5,812
  • 5
  • 29
  • 46
  • 2
    Allocation is the process of dividing up a larger region. The sections are allocated from system memory at run-time, the global variables are allocated from the section at compile-time. (And if we wanted to go further, we can talk about memory modules being allocated to a particular personal computer when the computer is purchased.) We don't usually say that a bulk copy "allocates" parts of the block. – Ben Voigt Sep 26 '11 at 17:20
  • @Ben Voigt Do you have any documentation on this? My interests are in low level coding and such, so I'd like to read about it further! – MGZero Sep 26 '11 at 17:36
  • 2
    You mean the [definition](http://www.merriam-webster.com/dictionary/allocate)? It might help to think of the process of hibernation (aka suspend-to-disk). When you resume a computer, the entire content of memory gets bulk copied from an image of the state when hibernation occurred. You'd say the memory content gets loaded, or copied, or such. But you wouldn't say that 400 million allocations take place during resume. The section containing globals is the same way, it's allocated at build time, and then just copied into memory at run-time, keeping the existing structure. – Ben Voigt Sep 26 '11 at 17:43
  • I see, so it sets aside where in memory these globals will appear and how much memory they take up, which is then used on run-time to actually initialize the globals. – MGZero Sep 26 '11 at 17:49
  • Right. Now we get into the difference between global constants and global variables, global constants (often called `.cdata`) are copied from disk into memory. For global variables (often `.data`) the loader just grabs a big enough chunk of memory for all variables combined and zeroes the whole thing. In any case, the layout is completely determined at compile time. After the big block is copied in, then the run-time library will start running constructors on individual objects. – Ben Voigt Sep 26 '11 at 17:55
4

Your program doesn't allocate anything during compile-time - I think you mean run-time.

Vector allocates what it holds on the heap (vec.size() * sizeof(/* what you are holding*/)) - it holds sizeof(std::vector<>) on where it is allocated. Global variables may be stored anywhere, it depends on the implementation.

Pubby
  • 51,882
  • 13
  • 139
  • 180
  • On most systems there's an "initialized data" section in which all global variables are stored, the size of this section and the location of variables inside it are set during build (by the linker, not the compiler, but definitely NOT run-time) – Ben Voigt Sep 26 '11 at 15:45
  • @Ben Voigt AFAIK, the globals are allocated during load time, and initialized during run time. – Pubby Sep 26 '11 at 15:58
4

Well, vec is a global variable, so the memory for it is presumably allocated from the data segment. However, the memory for the contents of vec depends on the allocator. By default, I think that the memory for the contents is allocated from the heap.

istudy0
  • 1,313
  • 5
  • 14
  • 22