Nilesh
Nilesh

Reputation: 309

C++ global array allocation

I have a C++ global multidimensional array with static linkage. I am assuming it will be stack allocated (I can't find the relevant section in the standard). Is it allocated contiguously?

Another question: I want to convert these static global n-dim arrays to be allocated on heap. What is the easiest way considering I want to minimize code changes? I can think of converting the arrays to n-dim pointers and malloc'ing at the start of main and free'ing before exiting main. But I have to worry about the contiguous allocation. Anybody see a better way?

Thanks,

Nilesh.

Upvotes: 4

Views: 2634

Answers (3)

Mike DeSimone
Mike DeSimone

Reputation: 42805

I have a C++ global multidimensional array with static linkage. I am assuming it will be stack allocated (I can't find the relevant section in the standard).

It will not be on the stack; it will be in the global area. Globals and static-storage objects get their own region of memory that is not part of the heap nor the stack.

Further, stack (the standard calls it "automatic" storage) objects only last as long as the function call they're part of; globals are initialized before main() is called and destroyed after main() exits.

Is it allocated contiguously?

It could be, though I doubt the standard requires it. (Clarification: contiguous storage for a 1-D array is guaranteed, but there's no guarantee there aren't "gaps" between rows in 2-D and up arrays.) If you require contiguous allocation, declare the global array as a one-dimensional vector and use an inline function to convert multiple dimensions to the corresponding index. It's the same as what the compiler would have generated if contiguous storage were guaranteed.

I want to convert these static global n-dim arrays to be allocated on heap. What is the easiest way considering I want to minimize code changes?

Change the global declaration from being an array to a pointer. In this case, vectorizing the storage is strongly recommended. (No, I'm not talking about std::vector, I'm talking about reshaping into a 1-D vector.)

I can think of converting the arrays to n-dim pointers

No such beast. Closes thing is a pointer to an array of pointers, which then point to either vectors or arrays of more pointers, depth determined by number of dimensions. It would be a bear to set up, and also much slower than, the 1-d vector case above with a function to convert N-D coordinates to a 1-D index.

malloc'ing at the start of main and free'ing before exiting main.

This, except you don't have to free at the end unless you're using valgrind or similar to look for memory leaks. The OS frees all your allocations that aren't shared memory upon process exit.

So you get something like:

#include <stddef.h>

static const size_t kDimX = 5;
static const size_t kDimY = 20;
static const size_t kDimZ = 4;

inline size_t DimsToVector(size_t x, size_t y, size_t z)
{
    return (x * kDimY + y) * kDimZ + z;
}

float* data = 0;

int main()
{
    data = new float[kDimX * kDimY * kDimZ];

    // Read elements with: data[DimsToVector(x, y, z)]
    // Write v with: data[DimsToVector(x, y, z)] = k;

    delete[] data; // Optional.
}

There are fancier ways, probably one in Boost, which define classes and override operator [] to hide some of the ugly, but this is about the minimum to get you going.

Upvotes: 2

Sergey Sirotkin
Sergey Sirotkin

Reputation: 1677

1) The memory for globals is allocated somewhere "in memory". It is neither on the stack, nor on the heap. For instance, global constants are usually placed in read-only section of the executable. Strictly speaking, it's implementation dependent. Why do you need to know this?

2) Memory will be continuous.

Upvotes: 0

zneak
zneak

Reputation: 138041

It's not allocated on the stack. Global variables are "allocated" in a special memory segment.

As of making your multidimensional array "contiguous", the simplest surefire way I can think of without fighting too much against the type system is to make a typedef of the lower dimension and make a pointer to that type.

typedef int TenIntegers[10];
TenIntegers* ints;

int main()
{
    ints = new TenIntegers[50];

    // your code here
    ints[0][5] = 3;

    delete[] ints;
}

Upvotes: 1

Related Questions