Misunderstanding about how memory is created using malloc () / calloc ()
My concept for a way malloc()/calloc()
to create memory has always been that after the element is created, the address of the object remains the same. But a function that I often use to create an array of strings, and one that seems to have always worked well, recently led me to question my understanding, that is, object memory addresses can (and) be moved just by calling calloc/malloc
.
To illustrate, here is the function I used to create memory for an array of strings - char **
:
char ** CreateArrayOfStrings(char **a, int numWords, int maxWordLen)
{
int i;
a = calloc(numWords, sizeof(char *)); //create array of pointers
if(!a) return a; //required caller to check for NULL
for(i=0;i<numWords;i++)
{
a[i] = calloc(maxWordLen + 1, 1); //create memory for each string
}
return a;
}
On my system (Win7, 32bit compile, ANSI C) Line:
a = calloc(numWords, sizeof(char *)); //create array of pointers
Creates a block of contiguous memory, size for numWords char *
, in this case 7, which gives 28 bytes:
Memory scrolls from address 0x03260080 + 1C (0x0326009C)
Or:
a[0] is at 0x3200260080
a[1] is at 0x3200260084
a[2] is at 0x3200260088
a[3] is at 0x320026008C
a[4] is at 0x3200260090
a[5] is at 0x3200260094
a[6] is at 0x3200260098
Then I create memory for each line numWords
(7)
for(i=0;i<numWords;i++)
{
a[i] = calloc(maxWordLen + 1, 1); //maxWordLen == 5 in this example
}
This leads to the following:
This indicates that the pointer memory areas a[1] - a[6]
have changed.
Can someone explain how / why this is happening in malloc()/calloc()
?
source to share
It looks like you are comparing apples to oranges:
- When you print pointers
a[i] is at ...
, you are specifying the addresses of the elements inside the arraya
- However, when you hover over the memory layout, you are showing the values ββat these addresses, which are themselves pointers, so the whole picture looks confusing.
If you print the values ββin a[i]
before assigning the results to them calloc
, you should get all zeros because it is calloc
NULL
deduced from memory. After the assignments, you see pointers to 6-byte blocks on each a[i]
, which makes sense.
To summarize, your initial understanding of what happens when you allocate memory with malloc
and calloc
is correct: after allocating a chunk of memory, its address * remains unchanged.
* On systems with virtual memory, I have to say "its virtual address".
source to share
The memory of these addresses has not been changed. You create a 28-byte large block of space ( a
) and then for each item, dynamically allocating a second 6-byte block of space with its own address.
In other words, in item [1] (memory address 0x03260084
) the value is saved , there is a pointer to the memory address 0x32600D0
.
To check memory locations and values ββon each of them, try the following:
for ( i = 0; i < 8; i++ )
{
printf("a[%d] %p %p\n",i,&(a[i]),a[i]);
}
source to share
When you call calloc(numWords, sizeof(char *))
, you are asking the operating system to allocate numWords
pointers of size `` 4 bytes on your system '', so the resulting block is 4 * numWords
bytes, and it returns refer to the first one. Now you can store the addresses of the pointers that will contain the actual data. The nth call calloc(maxWordLen + 1, 1)
will then return the address in a block of size maxWordLen
and store it in the memory location it points to a[n]
, which is just the address returned by the first call to calloc
plus n * sizeof(char *)
.
source to share