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 tempstring
that 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.