Search code examples
cpointersmemoryheap-memorycalloc

calloc returns a pointer to itself


I have problems when allocating memory on a Tiva C launchpad (ARM Cortex M4), what I am trying to do is to dynamically allocate a pointer to pointers to structure inside another structure, at some point calloc() returns a pointer which is the same value as the address where the pointer is stored.

I find this a bit difficult to explain, so I made this code which illustrates what I want to do and that works perfectly fine on here, but it doesn't work the same way in my application.

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

typedef struct
{
    uint32_t    Pin;
    uint32_t    Port;
} fGpio_Pin;

typedef struct
{
    uint32_t    Mode;
    uint32_t    nPins;
    fGpio_Pin** Pins;
} fSpi_Mod;

fSpi_Mod* Spi;

void printSizes (void)
{
    printf("Size of uint8_t: %i bytes.\n", sizeof(uint8_t));
    printf("Size of uint16_t: %i bytes.\n", sizeof(uint16_t));
    printf("Size of uint32_t: %i bytes.\n", sizeof(uint32_t));
    printf("Size of uint64_t: %i bytes.\n", sizeof(uint64_t));
    printf("Size of fSpi_Mod*: %i bytes.\n", sizeof(fSpi_Mod*));
    printf("Size of fSpi_Mod: %i bytes.\n", sizeof(fSpi_Mod));
    printf("Size of fGpio_Pin**: %i bytes.\n", sizeof(fGpio_Pin**));
    printf("Size of fGpio_Pin*: %i bytes.\n", sizeof(fGpio_Pin*));
    printf("Size of fGpio_Pin: %i bytes.\n", sizeof(fGpio_Pin));
    printf("----\n");
}

void printStructure (fSpi_Mod* Spi_Mod)
{
    uint8_t i;

    printf("The address of the structure is 0x%X.\n", Spi_Mod);
    printf("The value of mode is 0x%X and address 0x%X.\n", Spi_Mod->Mode, &(Spi_Mod->Mode));
    printf("The value of nPins is 0x%X and address 0x%X.\n", Spi_Mod->nPins, &(Spi_Mod->nPins));
    printf("The value of Pins is 0x%X and address 0x%X.\n", Spi_Mod->Pins, &(Spi_Mod->Pins));

    for (i = 0; i < Spi_Mod->nPins; i++)
    {
        printf("#%i | The pointer that points to Gpio structure is 0x%X at address 0x%X.\n", i, *(Spi_Mod->Pins + i), &(*(Spi_Mod->Pins + i)));
        printf("#%i | The value of Pin of Gpio structure is 0x%X and address 0x%X.\n", i, ((*(Spi_Mod->Pins + i)))->Pin, &(((*(Spi_Mod->Pins + i)))->Pin));
        printf("#%i | The value of Port of Gpio structure is 0x%X and address 0x%X.\n", i, ((*(Spi_Mod->Pins + i)))->Port, &(((*(Spi_Mod->Pins + i)))->Port));
    }
    printf("----\n");
}

int main()
{
    uint8_t i = 0;

    printf(">>>> Begin program.\n");

    printSizes();

    Spi = (fSpi_Mod*) calloc(1, sizeof(fSpi_Mod));
    if (Spi == NULL) {
        printf("Insufficient memory.\n");
        return 1;
    }

    //printStructure(Spi);
    Spi->Mode = 0x05;
    Spi->nPins = 0x04;

    Spi->Pins = (fGpio_Pin**) calloc(Spi->nPins, sizeof(fGpio_Pin*));
    if (Spi->Pins == NULL) 
    {
        printf("Insufficient memory.\n");
        return 1;
    }

    //printStructure(Spi);

    for (i = 0; i < Spi->nPins; i++)
    {
        (*(Spi->Pins + i)) = (fGpio_Pin*) calloc(1, sizeof(fGpio_Pin));
        if ((*(Spi->Pins + i)) == NULL) 
        {
            printf("Insufficient memory.\n");
            return 1;
        }
    }

    printStructure(Spi);

    printf(">>>> End program.\n");
}

In my application, when I try to allocate four pointers of type "pointer to (fGpio_Pin*)" and cast it to (fGpio_Pin**), calloc() returns the address of Spi->Pins, so basically the address of Spi->Pins and its value are the same and it becomes a pointer to itself, and that is when problems begin to appear.

There is enough memory in the heap and calloc() doesn't return a NULL pointer, could this be implementation dependant? I am using TI ARM Compiler and Code Composer Studio, not gcc.

Perhaps I am missing something so I will keep looking. Thank you for your time.

Edit1:

This is the output of the code above, which works OK.

>>>> Begin program.                                                                                                                                                                                                                            
Size of uint8_t: 1 bytes.                                                                                                                                                                                                                      
Size of uint16_t: 2 bytes.                                                                                                                                                                                                                     
Size of uint32_t: 4 bytes.                                                                                                                                                                                                                     
Size of uint64_t: 8 bytes.                                                                                                                                                                                                                     
Size of fSpi_Mod*: 8 bytes.                                                                                                                                                                                                                    
Size of fSpi_Mod: 24 bytes.                                                                                                                                                                                                                    
Size of fGpio_Pin**: 8 bytes.                                                                                                                                                                                                                  
Size of fGpio_Pin*: 8 bytes.                                                                                                                                                                                                                   
Size of fGpio_Pin: 8 bytes.                                                                                                                                                                                                                    
----                                                                                                                                                                                                                                           
The address of the structure is 0x1DF7010.                                                                                                                                                                                                     
The value of mode is 0x5 and address 0x1DF7010.                                                                                                                                                                                                
The value of nPins is 0x4 and address 0x1DF7014.                                                                                                                                                                                               
The value of Pins is 0x1DF7030 and address 0x1DF7018.                                                                                                                                                                                          
#0 | The pointer that points to Gpio structure is 0x1DF7060 at address 0x1DF7030.                                                                                                                                                              
#0 | The value of Pin of Gpio structure is 0x0 and address 0x1DF7060.                                                                                                                                                                          
#0 | The value of Port of Gpio structure is 0x0 and address 0x1DF7064.                                                                                                                                                                         
#1 | The pointer that points to Gpio structure is 0x1DF7080 at address 0x1DF7038.                                                                                                                                                              
#1 | The value of Pin of Gpio structure is 0x0 and address 0x1DF7080.                                                                                                                                                                          
#1 | The value of Port of Gpio structure is 0x0 and address 0x1DF7084.                                                                                                                                                                         
#2 | The pointer that points to Gpio structure is 0x1DF70A0 at address 0x1DF7040.                                                                                                                                                              
#2 | The value of Pin of Gpio structure is 0x0 and address 0x1DF70A0.                                                                                                                                                                          
#2 | The value of Port of Gpio structure is 0x0 and address 0x1DF70A4.                                                                                                                                                                         
#3 | The pointer that points to Gpio structure is 0x1DF70C0 at address 0x1DF7048.                                                                                                                                                              
#3 | The value of Pin of Gpio structure is 0x0 and address 0x1DF70C0.                                                                                                                                                                          
#3 | The value of Port of Gpio structure is 0x0 and address 0x1DF70C4.                                                                                                                                                                         
----                                                                                                                                                                                                                                           
>>>> End program.  

In my application (I can't post images I don't have enough reputation):

After the calloc: After the calloc:


Solution

  • I think your first calloc call is allocating insufficient memory. From the screenshot of the debugger you posted:

    SpiRfid = (fSpi_Mod*) calloc(1, sizeof(SpiRfid));
    

    This will allocate only enough memory for the pointer, not the structure. You probably want

    SpiRfid = (fSpi_Mod*) calloc(1, sizeof(*SpiRfid));