-1

recently i am interest in learning UNIX System programming, i encount a problem about Three-dimensional pointer memory free, how to free the memory to avoid the memory leak. i want to free the memory in main() function, but i have no idea how to fix it cause i am not so familiar with c three-dimensional pointer, also how to free "char *t" in makeargv(). thanks so much.

Here is The Code:

int makeargv(const char *s, const char *delimiters, char ***argvp) {
    int error;
    int i;
    int numtokens;
    const char *snew;
    char *t;

    if ((s == NULL) || (delimiters == NULL) || (argvp == NULL)) {
        errno = EINVAL;
        return -1;
    }
    *argvp = NULL;                           
    snew = s + strspn(s, delimiters);         /* snew is real start of string */
    if ((t = malloc(strlen(snew) + 1)) == NULL) 
        return -1; 
    strcpy(t, snew);               
    numtokens = 0;
    if (strtok(t, delimiters) != NULL)     /* count the number of tokens in s */
        for (numtokens = 1; strtok(NULL, delimiters) != NULL; numtokens++) ; 

        /* create argument array for ptrs to the tokens */
    if ((*argvp = malloc((numtokens + 1)*sizeof(char *))) == NULL) {
        error = errno;
        free(t);
        errno = error;
        return -1; 
    } 
        /* insert pointers to tokens into the argument array */
    if (numtokens == 0) 
        free(t);
    else {
        strcpy(t, snew);
        **argvp = strtok(t, delimiters);
        for (i = 1; i < numtokens; i++)
            *((*argvp) + i) = strtok(NULL, delimiters);
    } 
    *((*argvp) + numtokens) = NULL;             /* put in final NULL pointer */
    return numtokens;
}

int main(int argc, char *argv[]) {
    char delim[] = " \t";
    int i;
    char **myargv;
    int numtokens;

    if (argc != 2) {
        fprintf(stderr, "Usage: %s string\n", argv[0]);
        return 1;
    }   
    if ((numtokens = makeargv(argv[1], delim, &myargv)) == -1) {
        fprintf(stderr, "Failed to construct an argument array for %s\n", argv[1]);
        return 1;
    } 
    printf("The argument array contains:\n");
    for (i = 0; i < numtokens; i++)
        printf("%d:%s\n", i, myargv[i]);
    return 0;
}
  • 1
    Welcome to SO. You wrote " i have no idea how to fix it cause i am not so familiar with c ". In that case you should probably start with some (quite a lot in fact) tutorials and gain some basic knowledge about the problem you are asking. SO is not a tutorial nor code-writing service. – Maciej Jureczko Sep 19 '17 at 09:55
  • i have learn C programming in my collage school, but long time after, i forget some feature, and i will learn it again, thanks. – Poyang Chen Sep 19 '17 at 10:00
  • This is all rather horrible programming practice. It is not really something you should study. The reason why they use 3 levels of indirection is because they wish to return a pointer-to-pointer through the parameter list. However, this is widely considered bad practice, sarcastically known as "three star programming". Usually there are better ways to achieve the same result, such as using arrays of structures. – Lundin Sep 19 '17 at 11:51
  • Related reading on this topic: [Correctly allocating multi-dimensional arrays](https://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays). – Lundin Sep 19 '17 at 11:52

1 Answers1

1

Hello here's how to completely free a whole tri-dimensional pointer

#include <stdlib.h>

void    my_free_t3d(char ***tab)
{
 int    second_pointer;
 int    first_pointer;

 first_pointer = 0;
 while (tab[first_pointer] != NULL)
 {
    second_pointer = 0;
    while (tab[first_pointer][second_pointer] != NULL)
    {
        free(tab[first_pointer][second_pointer]);
        second_pointer++;
    }
    free(tab[first_pointer]);
    first_pointer++;
 }
 free(tab);
 }

I'll add the way I use to malloc a t3d so we can see the logic behind this free function.

int main()
{
    char ***tab;
    int i = 0;
    int j = 0;
   //I don't check malloc return values just for the example so it's more clear.        
    tab = malloc(sizeof(char **) * 10);
    while (i < 10)
    {
        j = 0;
        tab[i] = malloc(sizeof(char *) * 10);
        while (j < 10)
            {
                tab[i][j] = malloc(sizeof(char) * 10);
                j++;
            }
        i++;
    }
    my_free_t3d(tab); //Here's our memory freeing function
    return 0;
}

so basically I just start freeing the space allocated for the strings (contained in tab**). Then I delete the space allocated for the 2 dimensional pointers (tab*) and then I free the space allocated for the 3 dimensional pointers (tab).

If you don't free in that order and you directly free tab for example, you wont be able to access tab[I] or tab[I][J] but their memory will still be allocated.
Hope it helps you for your program.

Cjdcoy
  • 317
  • 1
  • 2
  • 12
  • Simple and efficient, though I would like to add that `while (something != NULL)` is redundant, and you just need `while (something)` cuz C is awesome – Adalcar Sep 19 '17 at 14:39
  • 1
    Rather than `tab[i] = malloc(sizeof(char *) * 10);`, consider `tab[i] = malloc(sizeof *(tab[i]) * 10);`. Easier to code correctly, review and maintain. – chux - Reinstate Monica Sep 19 '17 at 17:20
  • 1
    @chux Oh yea I forget that It's possible to sizeof directly the variable and not its type, I'll try to remember that for the next time. thank's. – Cjdcoy Sep 20 '17 at 04:29