Home > Net >  looping array of pointers to free them makes program crash in c
looping array of pointers to free them makes program crash in c

Time:11-20

Full code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void printarray(int* array, int arraysize){
    for (int i = 0; i<arraysize; i  ){
        printf("%d\n", *array);
        array  ;
    }
}

void printStrArray(char** array, int arraysize){
    int j = 0;
    for (int i = 0; i<arraysize; i  ){
        j = 0;
        while (array[i][j] != '\0'){
            printf("%c", array[i][j]);
            j  ;
        }
        printf("\n");
    }
}
int isStringInArray(char* string, char** stringArray, int arrayLen){ // returns 1 if string is contained in the array.
    for (int i = 0; i < arrayLen; i  ){
        if (strcmp(string, stringArray[i]) == 0){
            //printf("%s is equal to %s %d\n", string, stringArray[i], i);
            return 1;
        }
    }
    return 0;
}

int lenstring(char* string){ // checks string length (works only if string has null character at the end.)
    char currchar = string[0];
    int strlen = 0;
    while (currchar != '\0'){
        strlen  ;
        currchar = string[strlen];
    }
    return strlen;
}

char** riassemble(char* stringa){
    char** riassembleds = calloc(1, sizeof(char*));
    char* charLen = malloc(sizeof(char));
    riassembleds[0] = charLen;
    int riassembledLen = 1;
    int stringalen = lenstring(stringa);
    char tempstring[stringalen];
    strcpy(tempstring, stringa);

    for (int i = 0; i < stringalen; i  ){
        for (int j = 0; j < stringalen; j  ){
            tempstring[i] = stringa[j];
            tempstring[j] = stringa[i];
            //printf("%s\n", tempstring);
            if (isStringInArray(tempstring, riassembleds, riassembledLen) == 0){
                riassembleds = realloc(riassembleds, (riassembledLen 1)*sizeof(char*));
                riassembledLen  ;
                riassembleds[riassembledLen-1] = calloc(stringalen, sizeof(char));
                printf("%p\n", riassembleds[riassembledLen-1]);
                strcpy(riassembleds[riassembledLen-1], tempstring);
            }
            strcpy(tempstring, stringa);
        }
    }
    *charLen = (char)riassembledLen;

    riassembleds[0] = charLen; /*return the array with the length of the it casted into a char pointer as the first element*/
    return riassembleds;
}


int main(int argc, char *argv[]){
    char** array = riassemble("ciao");

    int arraylen = (int)(*(array[0]));
    printf("\n%d\n", arraylen);
    printStrArray(array, arraylen);

    for (int i=0; i<arraylen; i  ) {
        free(array[i]);
    }
    free(array);    
    return 0;
}

i'm making a function that returns an array of pointers to a char, in which the first element is a pointer that points to the length of the array casted into a char.

When i try to free the elements in the array with

    char** array = riassemble("ciao"); /*Creates the array*/

    int arraylen = (int)(*(array[0])); /*Gets the length*/

    for (int i=0; i<arraylen; i  ) {
        free(array[i]);
    }

The program crashes after trying to free the second element of the array which is defined here:

riassembleds = realloc(riassembleds, (riassembledLen 1)*sizeof(char*));
riassembledLen  ;
riassembleds[riassembledLen-1] = calloc(stringalen, sizeof(char));
printf("%p\n", riassembleds[riassembledLen-1]);
strcpy(riassembleds[riassembledLen-1], tempstring);

I really don't understand why this happens, one thing i noticed is that if i print the pointers that it's trying to free, they're not the same as when i print them right after allocating them in the riassemble function, but other than that i have no idea what i'm doing wrong.

edit: i was wrong about the fact that they're not the same, they actually are, i got confused.

CodePudding user response:

Your function lenstring will return the length of the string without the terminating null character.

Therefore, the line

char tempstring[stringalen];

will create an array tempstringthat is sufficient in size to store the string stringa without the terminating null character.

However, the function call

strcpy(tempstring, stringa);

requires that tempstring is large enough to store stringa with the terminating null character. You are therefore writing to tempstring out of bounds, invoking undefined behavior.

In order to fix this, I recommend that you change the line

char tempstring[stringalen];

to:

char tempstring[stringalen 1];

The line

riassembleds[riassembledLen-1] = calloc(stringalen, sizeof(char));

has the same problem, as it only allocates sufficient space without the terminating null character, which causes the line

strcpy(riassembleds[riassembledLen-1], tempstring);

to invoke undefined behavior for the same reason.

Therefore, the line

riassembleds[riassembledLen-1] = calloc(stringalen, sizeof(char));

should be changed to

riassembleds[riassembledLen-1] = calloc(stringalen 1, sizeof(char));

I was able to find these errors very easily by using AddressSanitizer on your program.

  • Related