1

The goal is to read in 105 words in from a file and assign them to an array. The array is initialized to

char **array = (char**)malloc(*capacity * sizeof(char*)); 

where capacity is set to 50.

I'm trying to make it so this function is called when 50 words have been read in and the 51st is being ready to. The initial allocation for the array should be space for 50 pointers. If the array ever gets full (i.e., wordCount equals current capacity), and there's a word to insert, I will double the capacity of the array (i.e., malloc a new array of twice the current size, copy the strings over into the front half of the newly allocated array, and free the space used by the old array. I am not allowed to use realloc. I would just like help fixing the way to do this using my method. Please do not suggest alternate methods.

So I keep getting a segmentation fault and I don't understand why. Any advice?

int doubleArraySize(char ***array, int count, int *capacity){ 
    char **temp = (char**)malloc(*capacity * sizeof(char*)); 
    if (temp = NULL){ 
        return -1; 
    } 

    int i = 0; 
    while(i<count){ 
        temp[i] = *array[i]; 
        i++; 
    } 

    i = 0; 
    while(i<count){ 
        free(*array[i]); 
        i++; 
    } 

    free(*array); 
    *array = temp; 
    return 0; 
}

And yes I am not allowed to use realloc. I was specifically told to create a new array of double the size and copy the elements to the first half then free the old one. Also in a debugger i am using, it says the problem lies in the line

temp[i] = *array[i];

but i have no idea why. Thank you in advanced!

Aris94
  • 71
  • 2
  • 8

2 Answers2

4

Change *array[i] to (*array)[i] in temp[i] = *array[i];.
The subscript operator [] has higher precedence than the dereference operator *, thus (*array)[i] designates the i-th element of a char* array, while *array[i] is dereferencing the i-th element of a char** array. According to the logic of your program, the former is what you really want, so the parentheses can't be omitted.

And you shouldn't free any of the individual (*array)[i], since you actually store them in the newly allocated array. Just free(*array) is enough.

neverhoodboy
  • 1,040
  • 7
  • 13
1

First of all, don't cast the result of malloc. It has no benefit and can cause bugs if you forget to include the header stdlib.h. Read this for details - Do I cast the result of malloc?

Now, there is a problem with the statement you use to copy the old array into the new one -

temp[i] = *array[i];

The array subscript operator [] has higher precedence than the dereference operator *. Therefore the above is the same as -

temp[i] = *(array[i]);

array is of type char *** and points to an array of objects of type char **. array[i] evaluates to *(array + i) which does illegal memory access invoking undefined behaviour. Therefore, you should change the statement to

temp[i] = (*array)[i];

which means dereference array first and then get the ith element in the buffer pointed to by array. I suggest using the standard library function memcpy to copy the old array into the new one. Also, to free a block of dynamically allocated buffer, you just need to pass the base address of the buffer and the entire block is freed.

#include <string.h>
#include <stdlib.h>

int doubleArraySize(char ***array, int count, int *capacity) { 
    char **temp = malloc(*capacity * sizeof *temp); 
    if(temp = NULL){ 
        return -1; 
    } 

    memcpy(temp, *array, count * sizeof **array);

    free(*array); 
    *array = temp; 
    return 0; 
}
Community
  • 1
  • 1
ajay
  • 9,402
  • 8
  • 44
  • 71
  • 1
    First of all, I want to thank you guys for being so helpful and teaching me rather than just giving me an answer. So my new function looks like this – Aris94 Mar 23 '14 at 17:43
  • First of all, I want to thank you guys for being so helpful and teaching me rather than just giving me an answer. So I deleted the while loop which freed each string. I removed the cast from malloc, and then changed each occurrence of *array[i] with (*array)[i]. However, when I ran the new program and printed out my new array of strings, weird symbols were showing up next to random words throughout. I tried messing around and eventually when I commented out free(*array), it worked perfectly. However, I know this will lead to memory leaks.Don't I have to free either *array or temp in some way? – Aris94 Mar 23 '14 at 17:52
  • @Aris94 you just need to pass the base address of the dynamically allocated array and the entire memory block will be freed. This may be happening because you are trying to free memory which has already been freed. Please check your `array` variable. – ajay Mar 23 '14 at 17:56
  • @Aris94: You might want to edit the question to add the modified version of your code so that people can help you figure out what actually goes wrong. – neverhoodboy Mar 24 '14 at 11:08