daniel.franzini
daniel.franzini

Reputation: 93

C malloc weird behavior on debug/release

I'm trying to use the C malloc/free functions in simple program.

void* alloc_array( const int size )
{
    void* p;

    p = malloc( size );
    if( p )
    {
        //memset(p, 0, size);
        return( p );
    }
    else
        return NULL;
}

void free_array( void* p )
{
    if( p )
    {
        free( p );
        p = NULL;
    }       
}

void** alloc_array_ptr( const int nPointers )
{
    void** p;   
    unsigned int size = AMOUNT_TO_ALLOC(nPointers, void*);

    p = malloc( size );
    if( p )
    {
        return( p );
    }
    else
        return( NULL );
}

void free_array_ptr( void** p, const int nPointers )
{
    unsigned int i;

    if( p )
    {
        for( i = 0; i < nPointers; i++ )
            if( p[i] )
            {
                free( p[i] );
                p[i] = NULL;
            }

        free(p);
        p = NULL;
    }
}
int main(int argc, char* agv[]) {
    // builds the string with the location of the ini file
    int inifile_size = 0;
    char* inifile;
    // gets the buffer size nedeed for the buffer
    inifile_size = GetCurrentDirectory(0, NULL);
    // allocates memory for the buffer
    inifile = (char*) alloc_array( AMOUNT_TO_ALLOC(inifile_size, char) );
    // fills the buffer with the current directory
    if( GetCurrentDirectory( inifile_size, inifile ) == 0 )
    {
        printf("GetCurrentDirectory failed! (ErrorCode: %u)\n", GetLastError());
        return( !MY_ERROR_OK );
    }
    strcat(inifile, "\\");
    strcat(inifile, "test.ini");    
    printf("INI File: %s\n", inifile);

    char** sessions;
    int nSessions = 0;
    int i;

    nSessions = getNumberOfSubkeys(str);
    printf("\nOK (%d sessions found)\n", nSessions);

    // allocating memory for the sessions array of char*
    sessions = (char**) alloc_array_ptr( nSessions );

    if( sessions == NULL )
    {
        printf("ERROR_IN_MEM_ALLOC (SESSIONS)\n");      
        return( MY_ERROR_MEM_ALLOC );
    }
    else
        printf("sessions: 0x%p\n", sessions);

    // allocating memory for each one of the char* in sessions
    for( i = 0; i < nSessions; i++ )
    {
        sessions[i] = (char*) alloc_array( AMOUNT_TO_ALLOC(MAX_KEY_LENGTH, char) );

        printf("sessions[%d]: 0x%p\n", i, sessions[i]);

        if( sessions[i] == NULL )
        {
            printf("ERROR_IN_MEM_ALLOC (SESSIONS[%d])\n", i);
            return( MY_ERROR_MEM_ALLOC );                   
        }
    }

    printf("\nSessions found:\n");

    if( readSubkeys( str, sessions ) == MY_ERROR_OK )
    {
        for( i = 0; i < nSessions; i++ )
        {
            printf("\t%s: ", sessions[i]);

            if( convert2ini(inifile, sessions[i]) == MY_ERROR_OK )
                printf("OK\n");
            else
            {
                printf("ERROR\n");
                return( !MY_ERROR_OK );
            }           
        }
    }
    else
    {
        printf("ERROR\n");
        return( MY_ERROR_OPEN_REGISTRY );   
    }

    // free the inifile array
    free_array(inifile);

    // free the array of char*
    free_array_ptr( (void**)sessions, nSessions );      

    // returns to OS
    return( MY_ERROR_OK ); 
}

This is a little tool to convert some program settings inside the windows registry to a ini file (Windows7, 64bits, 4Gb RAM).

readSubkeys fills the pre-allocated sessions array of char* with the names of the sessions it gets from registry key in str

getNumberOfSubkeys returns the number of subkeys inside a given in registry

The rest of the code is irrelevant for this. The problem is that when I'm allocating the memory for each one of the char*, inside the for loop, malloc fails. I'm using CodeLite to write this program and strangely enough malloc does not fail when I'm debugging the code step-by-step.

An image of a running of this is program is here. running

Could someone please, give me some advice?

Upvotes: 1

Views: 1703

Answers (3)

daniel.franzini
daniel.franzini

Reputation: 93

Thank you all for the tips.

The problem was that I was not allocating memory correctly at a point earlier in the program. Strange enough this part of the software worked but the subsequent memory allocation failed. What I did to solve is that I calculated the correct size of the memory I had to malloc, including several strcat calls to add the separator and the filename. Then, the software worked just fine. I rewrote the problematic part and it looks like this.

    // builds the string with the current directory

    // gets the size nedeed for the buffer
    current_path_size = GetCurrentDirectory(0, NULL);

    // allocates memory for the buffer
    current_path = (char*) alloc_array( AMOUNT_TO_ALLOC(current_path_size, char) );

    // gets the current directory
    if( GetCurrentDirectory( current_path_size, current_path ) == 0 )
    {
        printf("GetCurrentDirectory failed! (ErrorCode: %u)\n", GetLastError());
        return( !MY_ERROR_OK );
    }

    // builds the string with the location of the ini file

    // calculates the total amount of memory to alloc
    total_size = current_path_size + strlen(CHAR_SEPARATOR) + strlen(PUTTY_FILENAME) + 1;

    // allocates memory for the full path + filename of the ini file
    ini_file = (char*) alloc_array(AMOUNT_TO_ALLOC(total_size, char));

    // fills the buffer with the path + separator + filename + leading '\0'
    strcat(ini_file, current_path);
    strcat(ini_file, CHAR_SEPARATOR);
    strcat(ini_file, PUTTY_FILENAME);
    ini_file[total_size - 1] = '\0';

The one thing that left without response is why the debugger did not crashed the code. I still need to do further research on this.

Upvotes: 0

Aditya Tantry
Aditya Tantry

Reputation: 65

Sorry that I have to post this as a answer. I still don't have privileges to post comments. In the first malloc statement, you are typecasting the return of malloc to a pointer-to-a-pointer. So, in the for-loop, when you say sessions[0] it will contain the address of the first location 0x00701760(after first malloc). You increment your for loop to sessions[1]. This technically is not possible. Since there is no next value in sessions. You actually need to increment the value contained in sessions[0]. It could be like *sessions++. What I am trying to say is you should increment 0x00701760 to 0x00701762 and do a malloc to this. So 0x00701762 now contains the address of the newly allocated memory. Next would be 0x00701764 and then 0x00701766. Incrementing the sessions[] would be causing a error or atleast accessing invalid memory. Hope this suggestion helps.

Thanks Aditya

Upvotes: 1

Scott Presnell
Scott Presnell

Reputation: 1538

strangely enough malloc does not fail when I'm debugging the code step-by-step.

This statement likely means you have a memory allocation error somewhere else in your code that causes this block (e.g. the malloc() call, or an assertion) to fail. We don't really have enough information to completely debug this without more of your code.

Upvotes: 2

Related Questions