1

Considering this:

typedef struct
{
 int x;
 int y;
} Coordinate;

Coordinate places[100];
  • Is the memory for the 100 Coordinates allocated automatically? Or does it allocate one at a time when you initialize each element of the array?

  • What happens if you adress uninitialized parts of the array? Does this trigger an error?

4
  • The memory is allocated automatically, when you declare places. If you go out of bounds you will probably cause a segmentation fault. Commented Feb 23, 2010 at 13:55
  • 2
    Because this is tagged C++, you don't need to use a C typedef idiom. Use struct Coordinate {...}; instead. This defines a type called Coordinate in C++. Commented Feb 23, 2010 at 14:00
  • @Beta, that's an answer, not a comment. Why don't you put it in an answer? Commented Feb 23, 2010 at 14:01
  • @paxdiablo, because it's trivial. I could have gone into detail about uninitialized memory, read vs. write, heap corruption, run-time errors, countermeasures, safeguards, valgrind and so on, but I knew someone would beat me to it. Commented Feb 23, 2010 at 14:39

7 Answers 7

2

How memory is reserved depends on where the array declaration is declared. If it is declared in global scope (i.e. outside a function) then the 800 bytes (assuming an integer is 32-bits long) is made available to the whole program immediately. If it is inside a function these 800 bytes are allocated on the stack and are inaccessible when the function exits.

So in question 1: Yes the whole 100 coordinates are available in the same scope as the declaration.

Question 2: You can access all 100 elements at any time but their contents will be uninitialised. So it's safe to write to all 100 indices immediately, just don't read from them until you've initialised them.

If you wish to initialise them all (say to 0,0) then make this declaration instead:

struct Coordinate
{
    int x;
    int y;

    Coordinate () : x(0), y(0) { }
};

of course, this only works in C++. If you are writing code in C then you don't have the facility to automatically initialise elements in an array.

Reading outside the bounds of 0 to 99 will give undefined behaviour. At best, the runtime will detect that an give you a runtime error. At worst, you will corrupt the memory and will not know until the program finishes leaving you wondering where the error is. So be careful and make sure your indices are within bounds.

Common practice is to provide a function to access the array (don't access the array directly) and there you can do an assert check to test for the array index.

Best of luck

Sign up to request clarification or add additional context in comments.

4 Comments

Small note: If the array is declared at global scope, then int values will be initialized to 0, even without the Coordinate() constructor.
Also at local scope but with static storage class, zero initialisation is guaranteed.
With respect to the "common practice" paragraph, since this is C++ a std::vector type accessed using the at() member function rather than the [] operator would be generally a better (or at least less C-like) solution, since it throws an exception if the index exceeds the bounds.
I've tested the zero initialisation and you're right - I actually didn't know that. Thanks!!! However, is this something that is guaranteed by the language or is it something the loader does when it allocated memory for global data?
0

1/ Yes, there is an allocation. And destructor call and deallocation at the end of the block.

2/ All elements of the array are initialized with the default constructor (it is an compile time error if there is no default constructor). If the default constructor doesn't initialize something, it is the same behavior if that object if part of an array or not (i.e. undefined value which can cause undefined behavior if they are read)

1 Comment

Just to clarify. All 100 objects are allocated at once (or at compile time if the array is global), and immediately the default constructor is called on each (or when the program starts, if the array is global). Accessing uninitialized parts of the array (as opposed to out of bounds parts) may or may not trigger an error, depending on the type of access. I believe the standard mandates that it is undefined behavior. Typically, reading an uninitilized int won't trigger an error, whereas dereferencing a pointer usually will.
0

first : yes, the area is reserved, but its content will be invalid until the areas are properly initialized
second : many things can happen, one is acces violation or nothing, but making your system to operate erroneously

1 Comment

A slight correction on the second part... Addressing uninitialized parts of the array won't cause an access violation because the memory has been allocated - it may just be filled with garbage data which can cause erroneous behavior.
0

The memory is allocated automatically on the stack, so you have to be careful of how large you make the array. Every OS has differing sizes of stacks, but there is a limit nonetheless. Typically a small number KB per thread/process.

When you access uninitialized members of the array, you will read whatever was there previously from another stack frame or whatever random garbage was in that memory page. Hence its considered good practice to initialize the array with a memset or an array initializer.

Comments

0

1) The memory is allocated as a single contiguous block.

2) If instantiated statically (i.e. not an auto variable), the memory shall be initialised to zero, otherwise it will be uninitialised and the content shall be undefined. Accessing these undefined values does not trigger any error, if you read junk data and act upon it the behaviour will be determined entirely by the non-deterministic content, and what your code does with it.

If you want automatic initialisation you can define a default constructor. In C++ a struct is virtually identical to a class (the differences are with default member visibility and inheritance), and can have member functions, constructors and destructors.

Comments

0

In your example, all the instances are allocated at once - all items zero to 99 inclusive are valid. If you used a type with a constructor, all 100 would be constructed.

EDIT - as others have noted, just because it's constructed doesn't mean anything has been initialised. The default constructor for "int" leaves it untouched (it's your job to initialise it to whatever you want). The default constructor for "struct" calls the constructors for its members. That is, constructing doesn't mean much here - but the memory is allocated and ready for you to (initialise and) use.

The first uninitialised "part of the array" isn't a part of the array - it's going out of bounds. For example...

Coordinate mistake = places [100];  //  Above the upper bound

This is "undefined" behavior. You may get an crash (some kind of memory-related exception from the processor). Your program may carry on happily working, ignorant of the fact that it's using invalid junk data. In the above case, since what's happening is fairly obvious, you'll probably get a compiler warning - but that won't generally be the case.

If you write to an out-of-bounds array index, you may be corrupting other variables or the return address of your function or just about anything, so the behavior of your whole program from that point onwards is undefined. This is the basis of one of the largest whole classes of security flaws and "exploits".

An std::vector is another way of creating arrays. It doesn't allocate all items immediately - it's a dynamic array that allows for (and manages) resizing. However, it won't catch out-of-bounds indexes any more than the basic C-style array will.

Comments

0

There would be no difference in the behaviour of the array based on the type. So, the allocation of memory is done once you create the array and when uninitialized variables would have some garbage data.

To initilize all the elements of an array, you can have a default constructor to initilaize them to a value required or a constructor with default parameters where the values could be initialized to a value required when no values are provided.

Eg:

struct Coordinate
{ 
    int x;
    int y;

    Coordinate (int x1 = 0, int y1 = 0) : x(x1), y(y1) { } 
};

This works with arrays and all the values in the array will be initiliazed to zero(0).

To initilize all the elements of an array of primitive data type to zero(0)

int places[100] = { 0 };

Didn't verify whether it works for the user defined types, though. You can give a try.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.