I attempted implementation of a new feature on working code. However, I know from commenting out that the following lines of code are causing my program to crash.
tmp = (char*)realloc(list->array[list->size], sizeof(char)*nameLength);
list->array[list->size] = tmp;
list->array[list->size]
is defined in a struct in a .h file. list->size
is an int that increases as the size of the array increases. I know that the .h file is correct and am pretty certain the rest of my code was written correctly because I tested it all. However I can't seem to figure out this realloc
function. Can somebody please help me? I've searched stackoverflow and couldn't find the answer. This is my first time posting a question on stackoverflow. I hereby promise to help others on this site if I can get some help with this problem.
typedef struct ArrayList
{
// We will store an array of strings (i.e., an array of char arrays)
char **array;
// Size of list (i.e., number of elements that have been added to the array)
int size;
// Length of the array (i.e., the array's current maximum capacity)
int capacity;
} ArrayList;
I didn't want to clutter the post with long code. But just in case someone can find something I overlooked I am posting my main.c.
int main(void)
{
int i;
char buffer[32];
ArrayList *L1 = createArrayList(-1);
FILE *ifp = fopen("names.txt", "rb");
//Read all names from the file and add them to L1.
while (fscanf(ifp, "%s", buffer) != EOF)
put(L1, buffer);
//printf("the size is %d", L1->size); //test
for(i=0; i<L1->capacity; i++) { //free columns
free((void*)L1->array[i]);
}
free((void*)L1->array); //free rows
free((void*)L1); // free struct
system("pause");
return 0;
}
char * put(ArrayList *list, char *str)
{
int i = 0,length = 0, nameLength;
char* tmp, tmp2;
//free((void*)list->array[list->size]); //free columns
//list->array[list->size] = NULL; //set old pointer to NULL
nameLength = strlen(str)+1; //Aquire length of name +1
tmp = (char*)realloc(list->array[list->size], sizeof(char)*nameLength);
list->array[list->size] = tmp;
//list->array[list->size] = str;
//strcpy(list->array[list->size], str);
printf("the name in the .txt file is %s: put \n", list->array[list->size]);
//if array is full add space
length = (list->capacity)*2 + 1;
//if ( list->capacity <= list->size ) {
ArrayList *nlist = expandArrayList(list, length);
//}
list->size ++;
}
ArrayList *expandArrayList(ArrayList *list, int length)
{
int i;
//create newCharArray
char **newCharArray = (char*) malloc(sizeof(char*)*(length+1)); //alocate rows//2
for(i=0; i<length+1; i++) { // should fill ten rows + 1//2
newCharArray[i] = malloc(100 * sizeof(char*)); //alocate Columns
newCharArray[i] = "yoO";
}
//copy old list-Array into newCharArray
for( i=0; i<list->capacity; i++) { //was length
newCharArray[i] = list->array[i];
}
//print the values you inserted //test
for( i=0; i<list->capacity + 1; i++) {//2
printf("the value in slot %d is %s : expandArrayList \n", i, newCharArray[i]);
}
//free the list->array columns and rows
for( i=0; i<list->capacity; i++) {
free((void*)list->array[i]);
}
free((void*)list->array);
//set adress of newCh.. = our old Struct
list->array = newCharArray;
//print to test we did what was asked //test
for( i=0; i<length + 1; i++) {//2
printf("value in slot %d is %s : expandArrayList \n", i, list->array[i]);
}
return list;
}
ArrayList *createArrayList(int length)
{
int ncolumns, nrows, i;
char stringVar[5]; //set rows = empty
if(length < DEFAULT_INIT_LEN)
length = DEFAULT_INIT_LEN;
nrows = length;
ArrayList *theArray;
theArray = (ArrayList*)malloc (sizeof(struct ArrayList)); //alocate struct
theArray->array = (char*)malloc(sizeof(char*)*(nrows)); //alocate Rows 10th row will be null
for(i=0; i<nrows; i++) { // should fill ten rows
theArray->array[i] = (char*)malloc(2 * sizeof(char)); //alocate Columns //realloc later
theArray->array[i] = '\0'; //(char*)"pointer char will be returned malloc(100*sizeof(char): char*100 will be alocated
}
//theArray->array[nrows] = '\0'; //should fill the 11'th pointer slot array index 10
theArray->capacity = nrows; //total rows that are available for use ("not including last null")
theArray->size = 0; //Amount of rows used
printf("capacity = %d :createArraylist \n", theArray->capacity);
return theArray;
}
In your expandArrayList()
function, you're wandering down your array, allocating storage for strings. After each allocation, however, you're immediately throwing away your pointer to allocated storage, and replacing it with a pointer to "yoO"
, a string literal. String literals are arrays of char, but they are not allocated with malloc(), do not belong to you, and you aren't allowed to free()
or realloc()
them. Slightly further down the same function, however, when you're trying to free the previous copy of the array list, guess what you're passing to free()
?
In createArrayList()
, you do nearly the same thing, except that each allocated pointer that you throw away, you're replacing with '\0'
, which is, effectively, a null pointer in this context.
Not to mention, how in expandArrayList()
, immediately after filling each slot with a newly malloc()
ed piece of memory (and then throwing it away...), you immediately copy the pointers from the old array list (which you subsequently also free()
...)