Understanding issues with dynamic memory allocation

Thread Starter

@vajra

Joined May 2, 2018
141
I have a question concerning dynamic memory allocation I have found lots of information use them But I have found no explanation of program executions.

I have the line of code below that I need to know

Code:
int *array =  (int  * )malloc(10 * sizeof(int));
can anyone give me a straight up explanation of this line so what happen when this line of code compile and execute as comparing to memory space

Thanks.
 

BobTPH

Joined Jun 5, 2013
2,024
It will allocate enough space for 10 integers and place its address in the variable “array”.

You can then access these 10 integers by using suscripts:

Bob
 

WBahn

Joined Mar 31, 2012
24,693
I have a question concerning dynamic memory allocation I have found lots of information use them But I have found no explanation of program executions.

I have the line of code below that I need to know

Code:
int *array =  (int  * )malloc(10 * sizeof(int));
can anyone give me a straight up explanation of this line so what happen when this line of code compile and execute as comparing to memory space

Thanks.
From a practical standpoint, you are asking the memory manager to allocate a block of memory that is at least large enough to store ten items each of which is the size of a int data type. The starting address of this block is then returned by the memory manager and stored in the variable 'array', which has been declared as a variable whose value is the address at which a variable of type 'int' is stored.

As for what happens under the hood when the code is compiled and executed that is more involved and the details are completely up to whoever wrote the compiler. Generally there is a region of memory known as the "heap" and the memory manager has some means of tracking and marking blocks of memory that have been allocated or that are available for allocation. These are updated as you call malloc() and free() (or a handful of other functions).
 

Thread Starter

@vajra

Joined May 2, 2018
141
From a practical standpoint, you are asking the memory manager to allocate a block of memory that is at least large enough to store ten times each of which is the size of a int data type. The starting address of this block is then returned by the memory manager and stored in the variable 'array', which has been declared as a variable whose value is the address at which a variable of type 'int' is stored.
.
okay thank you It help me

I have another doubt I was looking this link
Code:
https://en.wikipedia.org/wiki/C_dynamic_memory_allocation
why we are using type casting in memory management
castiing
Code:
int *array =  (int  * )malloc(10 * sizeof(int));
without casting
int *array = malloc(10 * sizeof(int));
 

WBahn

Joined Mar 31, 2012
24,693
okay thank you It help me

I have another doubt I was looking this link
Code:
https://en.wikipedia.org/wiki/C_dynamic_memory_allocation
why we are using type casting in memory management
castiing
Code:
int *array =  (int  * )malloc(10 * sizeof(int));
without casting
int *array = malloc(10 * sizeof(int));
Most programmers believe that it is good practice to cast variables so that implicit type conversions are not used. This helps ensure that the program is doing exactly what you are telling it to do. In many instances proper casting is critical to getting code to work properly. It's also an indication to anyone reading your code that what is happening is happening by design instead of by chance.

Performing casts also gives the compiler information that it can use to do a better job of type checking to see if you are using your variables in a consistent manner. The better the information you give the compiler, then better it can serve your needs of helping you debug your code efficiently.

In this case, there is no requirement to perform the cast since malloc() returns a void pointer and a void pointer can be assigned to any compatible pointer type. There is also a school of thought that says that performing casts in this situation should not be done, although I have never found their arguments particularly persuasive. It largely comes down to a case of personal preference.
 

rsjsouza

Joined Apr 21, 2014
201
One interesting sentence I heard many years ago is along the lines of: "bring runtime errors to compile time".

The compilers I use tend to do a good job spotting incompatibilities among types, thus typecasting variables will "shush" these verification mechanisms and leave the burden to me (the coder) to think about all the possible inconsistencies the operation may carry.

I personally use the least amount of casts and rely on the implementation defined integer types instead, which carry the width of the variables on their name already (uint32_t, int64_t, etc.).
 

WBahn

Joined Mar 31, 2012
24,693
One interesting sentence I heard many years ago is along the lines of: "bring runtime errors to compile time".
I definitely agree with coding in a fashion so as to convert runtime errors to compile time errors as much as possible. For instance, a common test is to see if a file opened successfully, so you might see something like

if (fp == NULL)

If the common mistake is made of not using the equality relational operator and instead using the assignment operator, you get

if (fp = NULL)

in which case you make your file pointer NULL and, at the same time, ensure that the test intended to detect a NULL file pointer fails.

Whenever I have a constant I am comparing to, I put it on the left side so that I would write this as

if (NULL == fp)

and if (when) I make the same mistake it is now a compile-time error.

In this particular situation, I generally now avoid the operator altogether and use

if (!fp)

The compilers I use tend to do a good job spotting incompatibilities among types, thus typecasting variables will "shush" these verification mechanisms and leave the burden to me (the coder) to think about all the possible inconsistencies the operation may carry.

I personally use the least amount of casts and rely on the implementation defined integer types instead, which carry the width of the variables on their name already (uint32_t, int64_t, etc.).
I should clarify my stance because we are actually pretty much on the same page. I do not advocate blindly throwing typecasts at things just to make errors/warnings go away. A lot of people do exactly that and that is very bad programming practice. Anytime that I use a type cast is it very much a conscious decision reflecting the determination that I need/want to perform that cast. As part of that determination process I consider what the alternatives are that might avoid the need/desirability of doing the cast.
 

nsaspook

Joined Aug 27, 2009
6,279
We are all on the same page. I try to document somewhere the reason for the cast when I know it will be used later in something tricky.
C:
    dev->iobase = GPIO_BASE; /* bcm iobase */
    /* 
    * dev->mmio is a void pointer with 8bit pointer indexing, 
    * we need 32bit indexing so mmio is casted to a (__iomem uint32_t*) 
    * pointer for GPIO R/W operations 
    */
    dev->mmio = ioremap(dev->iobase, SZ_16K);
    if (!dev->mmio) {
        dev_err(dev->class_dev, "invalid gpio io base address!\n");
        return -EINVAL;
    }
http://learnlinuxconcepts.blogspot.com/2014/10/what-is-ioremap.html
https://www.oreilly.com/library/view/linux-device-drivers/9781785280009/266551f4-b749-4662-8132-741192fd77bc.xhtml
C:
static int32_t digitalReadGpio(struct comedi_device *dev,
    int32_t pin)
{

    pin &= 63;
    if ((ioread32((__iomem uint32_t*) dev->mmio + gpioToGPLEV [pin])
        & (1 << (pin & 31))) != 0)
        return HIGH;
    else
        return LOW;
}
 

Thread Starter

@vajra

Joined May 2, 2018
141
@WBahn , I wrote small code

I thought it may be help me for better understanding

Code:
#include<stdio.h>

#include<stdlib.h>

int main (void)

{
    int size=10, i=0;

    int *array= (int*)malloc((sizeof(int)) * size);

  
    /*insert element of array*/

    for(i=0; i < size; i++)
    {

         printf("%d \n", ( array + i));
    
    }    

   return 0;
 
}
This is output of code

12258776
12258780
12258784
12258788
12258792
12258796
12258800
12258804
12258808
12258812

I don't understand what are these value and How dynamic and static array are different as comparing to memory space
 

nsaspook

Joined Aug 27, 2009
6,279
We can assume the output of the code is the address of the data element in array as indexed (32-bit) by i starting from a zero offset.
 

MrSoftware

Joined Oct 29, 2013
1,564
Play with this:

Code:
#include<stdio.h>
#include<stdlib.h>
int main (void)
{
    int size=10, i=0;
    int *array= (int*)malloc((sizeof(int)) * size);
    // memset(array, 0, (sizeof(int)) * size);
    // Put some values into the array
    for(i = 0; i < size; i++)
    {
        array[i] = i * 2;
        // This does the same thing as the line above
        *(array + i) = i * 2;
    }
  
    for(i=0; i < size; i++)
    {
         printf("Array element %i address is %i \n", i,  ( array + i));
         printf("Array element %i content is %i \n", i,  *( array + i));
         printf("Array element %i content is %i \n", i,  array[i]); // Same as the line above
 
    }  
   return 0;
}
 

WBahn

Joined Mar 31, 2012
24,693
@WBahn , I wrote small code

I thought it may be help me for better understanding

Code:
#include<stdio.h>

#include<stdlib.h>

int main (void)

{
    int size=10, i=0;

    int *array= (int*)malloc((sizeof(int)) * size);

 
    /*insert element of array*/

    for(i=0; i < size; i++)
    {

         printf("%d \n", ( array + i));
   
    }   

   return 0;

}
This is output of code

12258776
12258780
12258784
12258788
12258792
12258796
12258800
12258804
12258808
12258812

I don't understand what are these value and How dynamic and static array are different as comparing to memory space
Your list may or may not mean anything because your format string doesn't match the value you are passing to printf(). You are telling it to print an 'int' value but you are passing it a pointer. Unless the pointers on your machine are the same size as ints, you are asking for trouble. Generally you want to use the "%p" format specifier when printing out pointers. For now I'll assume that this is not causing problems.

You have a variable called 'array' that gets set to the address of a block of memory that is big enough to hold 10 values of type 'int'. That may be 40 bytes or possibly 80 bytes on your system (it's unlikely to be anything else, but could be).

In your loop when you do "array + i" you are adding an integer to a pointer, which invokes pointer arithmetic (as opposed to integer arithmetic or floating point airthmetic). In pointer arithmetic the integer is implicitly multiplied by the size, in bytes, of whatever the pointer points to (as indicated by its type, which is why you can't do pointer arithmetic with a void pointer). So your output is a list of addresses of consecutive integers. We can tell from this list that the address of the block returned by malloc() is 12258776 and, by looking at the difference between successive addresses, that the size of an 'int' for this compiler is, indeed, 4 bytes.
 

MrAl

Joined Jun 17, 2014
6,488
I have a question concerning dynamic memory allocation I have found lots of information use them But I have found no explanation of program executions.

I have the line of code below that I need to know

Code:
int *array =  (int  * )malloc(10 * sizeof(int));
can anyone give me a straight up explanation of this line so what happen when this line of code compile and execute as comparing to memory space

Thanks.
Hi,

I read the thread but not sure if you got a direct answer yet.

I'll repeat the line in question:
Code:
 int *array =  (int  * )malloc(10 * sizeof(int));
First it looks for the size of an integer in bytes.
Then it multiplies that by 10.
Then it allocates that many bytes and points to that block with an integer pointer (or restated "a pointer to type integer").
Then it declares that block to be an array of integers pointed to with an integer pointer.
The memory available for use then can be addressed by using brackets with numbers 0 through 9.
So you get integer memory locations array[0] to array[9].
 

Thread Starter

@vajra

Joined May 2, 2018
141
Thanks to all of you. I understood my doubt

Firstly I have allocated dynamic memory to hold 5 integer using malloc function and after that I have allocated dynamic memory to hold 9 integer using ralloc functions

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

int main()
{
 
    int* ptr;
   
    int i;

    // Dynamically allocate memory using malloc()
    ptr = (int*)malloc(5 * sizeof(int));

    // Check if the memory has been successfully
    // allocated by malloc or not
    if (ptr == NULL)
    {
        printf("Memory not allocated.\n");
        exit(0);
    }

    // Memory has been successfully allocated
    printf("Memory successfully allocated using malloc.\n");

    // Get the elements of the array
       for (i = 0; i < 5; i++)
       {
           printf("The elements of the array are: ");
            scanf ("%d", ptr + i);          
        }

        // Print the elements of the array
        printf("The elements of the array are: ");
        for (i = 0; i < 5; i++)
        {
            printf("%d, ", *(ptr  + i));
        }
       
    // Dynamically allocate memory using malloc()
      ptr = (int*)realloc(ptr, 9 * sizeof(int));

    // Check if the memory has been successfully
    // allocated by malloc or not
    if (ptr == NULL)
        {
           printf("Memory not allocated.\n");
          exit(0);
        }
   
     printf("\n Enter the 4 more the elements of the array are: ");
   
         // Get the elements of the array
       for (i = 0; i < 9; i++)
       {
           printf("The elements of the array are: ");
            scanf ("%d", ptr + i);          
        }

        // Print the elements of the array
        printf("\nThe elements of the array are: ");
        for (i = 0; i < 9; i++)
        {
            printf("%d, ", *(ptr  + i));
        }    
   

    return 0;
}

Memory successfully allocated using malloc.

The elements of the array are: 1
The elements of the array are: 2
The elements of the array are: 3
The elements of the array are: 4
The elements of the array are: 5
The elements of the array are: 1, 2, 3, 4, 5,

Enter the 4 more the elements of the array are: The elements of the array are: 6
The elements of the array are: 7
The elements of the array are: 8
The elements of the array are: 9
The elements of the array are: 10
The elements of the array are: 11
The elements of the array are: 12
The elements of the array are: 13
The elements of the array are: 14

The elements of the array are: 6, 7, 8, 9, 10, 11, 12, 13, 14,
 

WBahn

Joined Mar 31, 2012
24,693
Notice that you are overwriting the original contents of your array instead of just entering the additional four elements as your print statement implies.

If this were the behavior you wanted, don't use realloc(). Instead, free() the original pointer and then use malloc() to get a new block of memory. The reason is that realloc() must first allocate a new block of memory without freeing up the original memory and then copy the contents from the original memory block to the new one before freeing the original memory. IF the memory manager can simply extend the original memory block (which requires sufficient free memory being available immediately after the original block) then this happens very quickly and cleanly. But in the very likely case that this is not possible, you have both blocks allocated at the same time, which could run you out of memory unnecessarily and you have the time needed to copy the contents over. For large blocks this can add up to quite a bit of space and time. So you normally only use realloc() when you need to preserver the contents of the original block and just change the size (usually to make it larger to accommodate additional data).
 

BobaMosfet

Joined Jul 1, 2009
795
I have a question concerning dynamic memory allocation I have found lots of information use them But I have found no explanation of program executions.

I have the line of code below that I need to know

Code:
int *array =  (int  * )malloc(10 * sizeof(int));
can anyone give me a straight up explanation of this line so what happen when this line of code compile and execute as comparing to memory space

Thanks.
Malloc() ie 'Memory Allocation' is a function that executes at run time, not compile time. Programs usually use both, small things done at compile time, but larger blocks or unknown memory needs are allocated at run time when the application has access to the heap. remember that malloc() must be balanced with a call to function to free that block and then it's pointer must be initialized to zero (aka NULL or NIL) so that if any part of the program tries to access memory using that dead ptr, it will crash with a reference to location zero (making it easy to find and fix).
 
Last edited:
Top