0

I try to make the memory allocation dynamically for table that contains the strings.
In my case, I have to use it dynamically, because I don't know how rows and columns the program will get.
Here is my code for two function:
1.The first is allocating the memory for the table only.
2.The second should free all allocated memory.
3.In the main function I'm allocating the memory for the string and copy the part of the predefined string (it's dummy code, for example only)

The result is "Runtime error" What am I doing wrong in the code?

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

char *** buildOptions(int rows, int columns) {
    int i=0;
    printf("1...\n");
    char ***options = (char ***)malloc(rows * sizeof(char **));
    printf("2...\n");
    for(i=0; i<rows; i++) {
        printf("3...\n");
        options[i] = (char **)malloc(columns * sizeof(char *));
        printf("4...\n");
    }
    return options;
}

void freeOptions(char ****options, int rows, int columns) {
    int i, j;
    for(i=0; i<rows; i++) {
        for(j=0; j<columns; j++) {
            if(*options[i][j])
                free(*options[i][j]);
        }
        if(*options[i]) {
            free(*options[i]);
        }
    }
    free(*options);
}

int main(void) {
    int i, j, k;
    char * str = "123456789abcdefghjkl\0";
    char ***options = buildOptions(5, 3);
    printf("Starting...\n");
    for(i=0; i<5; i++) {
        for(j=0; j<3; j++) {
            options[i][j] = (char *)calloc((i+j+2)+1, sizeof(char));
            strncpy(options[i][j], str, i+j+2);
        }
    }

    for(i=0; i<5; i++) {
        for(j=0; j<3; j++) {
            printf(">>options[%d][%d]=%s<<\n", i,j, options[i][j]);
        }
    }

    freeOptions(&options, 5, 3);

    //here I want to check if the memory is freed
    for(i=0; i<5; i++) {
        for(j=0; j<3; j++) {
            printf(">>options[%d][%d]=%s<<\n", i,j, options[i][j]);
        }
    }


    return 0;
}
Michael Vaysman
  • 277
  • 3
  • 16
  • 2
    Being a [three-star programmer](http://c2.com/cgi/wiki?ThreeStarProgrammer) is not a compliment. If you need something like that you either need to revisit your design or research different data structures. – Some programmer dude Apr 13 '16 at 08:10
  • I've counted 2 `malloc`s and 3 `free`s. To me, this immediately implies a logical error. Although it is not necessarily the problem at hand, I would recommend to implement functions `buildOptions` and `freeOptions` "symmetrically". – barak manos Apr 13 '16 at 08:10
  • Also please [read about how to ask good questions](http://stackoverflow.com/help/how-to-ask), and about [the XY problem](http://xyproblem.info/). What is the code attempting to do? What is the actual problem you try to solve? – Some programmer dude Apr 13 '16 at 08:11
  • @barakmanos There's a `calloc` in the `main` function as well. – Some programmer dude Apr 13 '16 at 08:11
  • @JoachimPileborg: Yes, I know, I've extended the comment due to that. – barak manos Apr 13 '16 at 08:11
  • 2
    Lastly, accessing memory that is not allocated to you or your program (like after freeing it) leads to *undefined behavior*. Don't do it. – Some programmer dude Apr 13 '16 at 08:13
  • I'm shocked this lived this long without someone reminding the OP to [not cast the result of memory allocations in C programs](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). Oh wait... nm. – WhozCraig Apr 13 '16 at 08:18

2 Answers2

2

Change the declaration of freeOptions to

void freeOptions(char ***options, int rows, int columns)

the call to

 freeOptions(options, 5, 3);

and the call to free() inside the freeOptions to

  free(options[i][j]);
GMichael
  • 2,726
  • 1
  • 20
  • 30
0

The cause of your segmentation fault is in how you access the array in freeOptions:

*options[i][j]

is the same as:

*(options[i][j])

bot options is the address of youroptionsinmain, so you should dereferenceoptions` first:

(*options)[i][j]

There's actually no need to pass in the char ***options from main by reference unless you plan to set *options to NULL in freeOptions. A better way to implement freeOptions has been pointed out in the other Michael's answer.

//here I want to check if the memory is freed

You can't find out whether the free has succeeded by accessing now invalid memory and causing undefined behaviour. The data may still be there, but it might as well contain garbage.

M Oehm
  • 28,726
  • 3
  • 31
  • 42