0

I am unable to free my 2D string array. It seems that it is unable to read the items in vars[0] and vars[1]. When I print the vars array I am able to print vars[0] and vars[1], however, I am unable to free them as the compiler does not recognize that there is any data in both indices.

I am using fscanf to read data from a text file. The file does not include '0' or '1'. I need to have '0' and '1' in the first 2 indices of the 2D string array. The data read from the input file consists of mainly strings. That is why I am using a 2D string array.

I am also reallocating the array as I will be adding more variables to the array as I progress through the file.

Is it how I am adding the '0' and '1' into the 2D array that is causing this problem?

int main(int argc, char **argv) {
    FILE *fp = fopen(argv[1], "r");

    int i;
    char type[17];
    int input, output;

    // fscanf for input
    fscanf(fp, "%s", type);
    fscanf(fp, "%d", &input);

    char **vars = malloc((input+2)*sizeof(char*));
    for (i = 0; i < input; i++) {
        if (i == 0) {
        vars[0] = malloc(17*sizeof(char));          
            vars[0] = "0\0"; 
        }
        if (i == 1) {
            vars[1] = malloc(17*sizeof(char));
            vars[1] = "1\0";
        }
        vars[i+2] = malloc(17*sizeof(char));
        fscanf(fp, "%16s", vars[i+2]);
    }

    fscanf(fp, "%s", type);
    fscanf(fp, "%d", &output);

    int length = output + input + 2;

    vars = realloc(vars, length*sizeof(char *));
    for (i = 0; i < output; i++) {
        vars[i+input+2] = malloc(17*sizeof(char));
        fscanf(fp, "%16s", vars[i+input+2]);

    printf("vars: \t");
    print2D(vars, (input+2));
    
    for (i = 0; i < length; i++) {
        free(vars[i]);
    }
    free(vars);
    fclose(fp);
    return EXIT_SUCCESS;
}

When I do not add '0' or '1' to the array, and read the first variable directly into vars[0] I do not get this problem.

However, I need to have '0' and '1' be in their respective spots as I will need to retrieve the respective values as I lookup the index number for each variable.

For instance: vars = {0, 1, a, b, c, d}; indx = {0, 1, 2, 3, 4, 5};

  • 1
    There's no need to put `\0` at the end of a string literal. The null terminator is added automatically. – Barmar Dec 05 '22 at 04:53

1 Answers1

1

Your problem is

vars[0] = malloc(17*sizeof(char));          
vars[0] = "0\0";

malloc returns a memory block at least size 17 (but you never check). Then you immediately lose your pointer to that block by pointing var[0] to the string literal "0\0" (this also creates a memory leak since you lose your pointer to the memory malloc returned). This is not the correct way to assign a string, use strcpy instead:

#include <string.h>
...

vars[0] = malloc(17*sizeof(char));          
if (vars[0] == NULL)
{
   // handle out of mem error how you want
}
else
{
   strcpy(vars[0], "0\0");
}

And the same for every other place you're doing this.

You should also check that you successfully open your file before using the file pointer:

FILE *fp = fopen(argv[1], "r");
if (fp != NULL)
{
   ....

Finally, take heed of Barmar's comment. I generally try to answer with as few modifications to the OP as possible, but he is 100% correct in that you don't need to add your own NUL terminator in a string literal, the compiler will do that for you. For example:

char* str1 = "foo";  // this creates the array { 'f', 'o', 'o', '\0' }
                     // which is 4 long and makes str1 point to it.
char* str2 = "foo\0"; // creates the array { 'f', 'o', 'o'. '\0', '\0' }
                      // which is 5 long. The manual '\0' isn't needed.
yano
  • 4,827
  • 2
  • 23
  • 35