What Is the Purpose of Allocating a Specific Amount of Memory for Arrays in C++

What is the purpose of allocating a specific amount of memory for arrays in C++?

When you go past the end of allocated memory, you are actually accessing memory of some other object (or memory that is free right now, but that could change later). So, it will cause you problems. Especially if you'll try to write something to it.

Why allocate memory? (C++)

Why is it neccessary to allocate memory?
Because that way, you mark the memory as yours. Nobody else can use it. It also verifies that there is in fact memory available. If your system only has 1000 bytes of memory, just picking byte 1500 to store some data at is a bad idea.

What happens if we use memory without allocating it?
Nobody knows. The address you write you might not exist. A different process might have already started using it, so you overwrite their data. The memory could be protected; in the former case, for instance, the operating system may notice that you are accessing memory another process has laid claim to, and stop you. You might own that region of memory, but a different part of the program is using it for some reason, and you've overwritten your own data.

Free access to memory through arrays with no bounds checking.
That code does not work... it functions as expected, at the moment, but that is not the same thing. Formally, that is undefined behavior, so the compiler can emit code to do anything it wants.

In what cases would assigning value to a non allocated memory location would be dangerous?
I gave some examples above. It is also possible to break your stack. When you call a function, the address the function should return to is stored. If you overwrite that value through careless memory access, then when you leave that function, who knows where you'll end up? Maybe the person exploiting your program... a common exploit is to load executable code into some part of memory, then use a bug in an existing program to run it. Once, on an embedded device I was working on, I had a fencepost error that resulted in my function returning into the middle of another instruction elsewhere. That should have crashed my chip, but as luck would have it the second half of that instruction was itself a valid instruction. The sequence of code that ended up running caused the device to gain sentience, and eventually finished the project we were working on itself. Now, it just plays WoW in my basement. Thus is the horror of undefined behavior.

Why do you need to allocate memory in c/c++?

Your question doesn't really make sense. ZeroMemory doesn't allocate memory; it just, well, sets bytes to 0. You can easily ZeroMemory an int, if you want. It's just that i = 0; is shorter to write.

In all cases ZeroMemory only works on memory that already exists; i.e. something else must have allocated it before.

As for actual allocation, C distinguishes three kinds of storage for objects:

  1. Static storage. These objects are allocated when the program starts and live for as long as the program runs. Example: Global variables.

  2. Automatic storage. These objects are allocated when execution reaches their scope and deallocated when execution leaves their containing scope. Example: Local variables.

  3. Dynamic storage. This is what you manage manually by calling malloc / calloc / realloc / free.

The only case where you really have to allocate memory yourself is case #3. If your program only uses automatic storage, you don't have to do anything special.

In languages like Java, you still have to allocate memory by calling new. Python doesn't have new, but e.g. whenever you execute something like [...] or {...}, it creates a new list/dictionary, which allocates memory.
The crucial part is really that you don't have to deallocate memory.

Languages like Java or Python include a garbage collector: You create objects, but the language takes care of cleaning up behind you. When an object is no longer needed1, it is deallocated automatically.

C doesn't do that. The reasons lie in its history: C was invented as a replacement for assembler code, in order to make porting Unix to a new computer easier. Automatic garbage collection requires a runtime system, which adds complexity and can have performance issues (even modern garbage collectors sometimes pause the whole program in order to reclaim memory, which is undesirable, and C was created back in 1972).

Not having a garbage collector makes C

  • easier to implement
  • easier to predict
  • potentially more efficient
  • able to run on very limited hardware

C++ was meant to be a "better C", targeting the same kind of audience. That's why C++ kept nearly all of C's features, even those that are very unfriendly to automatic garbage collection.


1 Not strictly true. Memory is reclaimed when it is no longer reachable. If the program can still reach an object somehow, it will be kept alive even if it's not really needed anymore (see also: Space leak).

Why does malloc need to be used for dynamic memory allocation in C?

Look up the concepts for stack and heap; there's a lot of subtleties around the different types of memory. Local variables inside a function live in the stack and only exist within the function.

In your example, int_array only exists while execution of the function it is defined in has not ended, you couldn't pass it around between functions. You couldn't return int_array and expect it to work.

malloc() is used when you want to create a chunk of memory which exists on the heap. malloc returns a pointer to this memory. This pointer can be passed around as a variable (eg returned) from functions and can be used anywhere in your program to access your allocated chunk of memory until you free() it.

Example:

'''C

int main(int argc, char **argv){
int length = 10;
int *built_array = make_array(length); //malloc memory and pass heap pointer
int *array = make_array_wrong(length); //will not work. Array in function was in stack and no longer exists when function has returned.

built_array[3] = 5; //ok
array[3] = 5; //bad

free(built_array)

return 0;
}

int *make_array(int length){
int *my_pointer = malloc( length * sizeof int);
//do some error checking for real implementation
return my_pointer;
}

int *make_array_wrong(int length){
int array[length];
return array;
}

'''

Note:
There are plenty of ways to avoid having to use malloc at all, by pre-allocating sufficient memory in the callers, etc. This is recommended for embedded and safety critical programs where you want to be sure you'll never run out of memory.

Do statically allocated arrays in C use all of their memory even when some of their elements are not specified?

If you have int array[1000000]; and only use a few of its initial members, then in some circumstances (if array is either static or a local of if it's a global and you're linking statically with link time optimizations) your toolchain can shrink/eliminate the array under the as-if rule.
(Note that global and static variables are not in effect uninitialized--the C standard mandates that they be zero-initialed.)

Gcc and clang do it, and clang does it even with mallocated arrays to the point that the entire malloc-free pair can be eliminated:

Example:

#include <stdio.h>
#include <stdlib.h>

//gcc and clang optimize out the array, only using
//the constants 1 and 10
int pr(void)
{
int array[1000000];
array[1] = 1;
array[10] = 10;
return printf("%d %d", array[1], array[10]);
}
//clang optimizes out the dynamic allocation of array,
//only using the constants 1 and 10
int pr1(void)
{
int r;
int *array = malloc(1000000);
if(!array) return -1;
array[1] = 1;
array[10] = 10;
r = printf("%d %d", array[1], array[10]);

free(array);
return r;
}

Example output assembly on x86-64 clang with -O3:

pr:                                     # @pr
mov edi, offset .L.str
mov esi, 1
mov edx, 10
xor eax, eax
jmp printf # TAILCALL
pr1: # @pr1
mov edi, offset .L.str
mov esi, 1
mov edx, 10
xor eax, eax
jmp printf # TAILCALL
.L.str:
.asciz "%d %d"

Check it out at https://gcc.godbolt.org/z/UmiA34.

Such optimizations are nonportable and twitchy, however. The simplest things such passing a pointer to an array to a function defined in a different translation unit can turn them off. I would avoid relying on them.

Dynamic allocation of memory for an array in C

if it is an array you might actually want to check out the calloc() function:

void* calloc (size_t num, size_t size);

It can be used like so:

/* calloc example */
#include <stdio.h> /* printf, scanf, NULL */
#include <stdlib.h> /* calloc, exit, free */

int main ()
{
int i,n;
int * pData;
printf ("Amount of numbers to be entered: ");
scanf ("%d",&i);
pData = (int*) calloc (i,sizeof(int));
if (pData==NULL) exit (1);
for (n=0;n<i;n++)
{
printf ("Enter number #%d: ",n+1);
scanf ("%d",&pData[n]);
}
printf ("You have entered: ");
for (n=0;n<i;n++) printf ("%d ",pData[n]);
free (pData);
return 0;
}

If you need to resize the array later look at the realloc function. (and yes it does keep the original data if succesfull)



Related Topics



Leave a reply



Submit