Thread: Reallocation of memory (3d dynamic matrix)

  1. #1
    C <3er
    Join Date
    Jul 2011
    Posts
    46

    Question Reallocation of memory (3d dynamic matrix)

    Hello again!
    Again problems with my project this time is the reallocation of a 3d dynamic matrix what is driving me mad... I'm trying to add a new column to the matrix and for this I'm trying to use the realloc routine in the cell pointer to pointer to pointer to char... the project is the same I explained here.
    This is what I have so far:
    Code:
    /* add_column: add a column to table t */
    void add_column(table *t){
        int i, j;
    
        // Increase columns count
        ++(t->cols);
    
        t->cell = (char ***) realloc(t->cell, t->rows * sizeof(char **));
    
        if(t->cell == NULL){
            printf("\n\t\tERROR: Out of memory\n");
            printf("\n\t\tPress any key to exit...\n");
            getchar();
            exit(EXIT_FAILURE);
        }
    
        for(i = 0; i < t->rows; ++i){
            t->cell[i] = (char **) realloc(t->cell[i], t->cols * sizeof(char *));
            if(t->cell[i] == NULL){
                printf("\n\t\tERROR: Out of memory\n");
                printf("\n\t\tPress any key to exit...\n");
                getchar();
                exit(EXIT_FAILURE);
            }
            for (j = 0; j < t->cols; j++){
                t->cell[i][j] = (char *)realloc(t->cell[i][j], NAME_MAX_LEN * sizeof(char));
                if(t->cell[i][j] == NULL){
                    printf("\n\t\tERROR: Out of memory\n");
                    printf("\n\t\tPress any key to exit...\n");
                    getchar();
                    exit(EXIT_FAILURE);
                }
            }
        }
    
        // Name & add new column
        printf("\nNew column's name:\n");
        printf("\nC%d: ", t->cols);
        fflush(stdin);
        gets(t->cell[0][t->cols]);
    
        for(i = 1; i < t->rows; ++i){
            printf("\nR%d C%d: ", i, t->cols);
            fflush(stdin);
            gets(t->cell[i][t->cols]);
        }
    }
    Remember I want to add a new column only, (I know the problems of using gets but I'll change that to fgets in a later stage...) the problem I'm having is sometimes the program crashes and I get a segmentation fault (again...)
    So first I need to know if the reallocation of memory is done correctly? (Because I'm not used to reallocate 3dimensional arrays) Thank you very much in advance!
    Last edited by beta3designs; 08-01-2011 at 09:07 AM.

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    If you are only changing the number of columns (and not the number of rows) then realloc'ing the main table pointer is fruitless, for you should be using the exact same number now (rows * sizeof pointer) that you were before. Why you decided to all of a sudden use columns I don't know.

    What you need to do is realloc each individual pointer to be one larger (since the rows are malloc'ed in a loop using (cols * sizeof pointer), and that will change).

  3. #3
    C <3er
    Join Date
    Jul 2011
    Posts
    46
    Sorry it was meant to be how it is now:
    Code:
    t->rows * sizeof(char  *)
    and not
    Code:
    t->cols * sizeof(char *)
    ... I don't know why I changed that neither lol...
    Quote Originally Posted by tabstop View Post
    What you need to do is realloc each individual pointer to be one larger (since the rows are malloc'ed in a loop using (cols * sizeof pointer), and that will change).
    But that's what this does doesn't it?:
    Code:
    for(i = 0; i < t->rows; ++i){
            t->cell[i] = (char **) realloc(t->cell[i], t->cols * sizeof(char *));
            if(t->cell[i] == NULL){
                printf("\n\t\tERROR: Out of memory\n");
                printf("\n\t\tPress any key to exit...\n");
                getchar();
                exit(EXIT_FAILURE);
            }
            for (j = 0; j < t->cols; j++){
                t->cell[i][j] = (char *)realloc(t->cell[i][j], NAME_MAX_LEN * sizeof(char));
                if(t->cell[i][j] == NULL){
                    printf("\n\t\tERROR: Out of memory\n");
                    printf("\n\t\tPress any key to exit...\n");
                    getchar();
                    exit(EXIT_FAILURE);
                }
            }
        }
    I first incremented the columns count so it should be reallocating the memory for each row to one column more...
    Should I remove the second loop and just reallocate the memory for the last column string?
    Last edited by beta3designs; 08-01-2011 at 09:18 AM.

  4. #4
    Registered User
    Join Date
    May 2011
    Location
    Around 8.3 light-minutes from the Sun
    Posts
    1,949
    You may want to take a look at C-FAQ 6.16 it goes through the explanation of dynamically allocating arrays, including, higher order ones very well.

    Additionally, read here on why fflush(stdin) is wrong.

    On a side note, you may want to take a step back and think about your program design. Under C99 you can dynamically allocate higher order arrays, however that doesn't mean you should. We don't get to many 3 star programmers around here.........
    Quote Originally Posted by anduril462 View Post
    Now, please, for the love of all things good and holy, think about what you're doing! Don't just run around willy-nilly, coding like a drunk two-year-old....
    Quote Originally Posted by quzah View Post
    ..... Just don't be surprised when I say you aren't using standard C anymore, and as such,are off in your own little universe that I will completely disregard.
    Warning: Some or all of my posted code may be non-standard and as such should not be used and in no case looked at.

  5. #5
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    And then your other error is:
    Code:
    t->cell[i][j] = (char *)realloc(t->cell[i][j], NAME_MAX_LEN * sizeof(char));
    This is irrelevant 95% of the time (because you are realloc'ing a pointer to the same size it already points to) and illegal the other 5% (your new column at the end contains an uninitialized pointer that must not be realloc'ed, but just malloc'ed).

  6. #6
    C <3er
    Join Date
    Jul 2011
    Posts
    46
    Thanks for the tip on fflush(stdin) didn't know about that...
    The project I'm writing is some kind of database and since it's very simple it doesn't ask the user which kind of input he wants to enter for each row, col, cell, etc. I'm just using char so everything can be written to it, that's why I'm using a 3 dimensional array so it acts like a matrix of strings, that's why I designed it like that and I got everything working correctly as far as I'm conecerned (modifying rows, cols, cells, etc.) just having issues adding rows and cols to the table. :S
    Ok thanks when I read your first response that's what I was thinking about tabstop :P
    Will try and see what happens

  7. #7
    C <3er
    Join Date
    Jul 2011
    Posts
    46
    Ok my new code is this:
    Code:
    void add_column(table *t){
        int i;
    
        // Increase columns count
        ++(t->cols);
    
        for(i = 0; i < t->rows; ++i){
            t->cell[i] = (char **) realloc(t->cell[i], t->cols * sizeof(char *));
            if(t->cell[i] == NULL){
                printf("\n\t\tERROR: Out of memory\n");
                printf("\n\t\tPress any key to exit...\n");
                getchar();
                exit(EXIT_FAILURE);
            }
            t->cell[i][t->cols - 1] = (char *) malloc(NAME_MAX_LEN * sizeof(char));
            if(t->cell[i][t->cols - 1] == NULL){
                printf("\n\t\tERROR: Out of memory\n");
                printf("\n\t\tPress any key to exit...\n");
                getchar();
                exit(EXIT_FAILURE);
            }
        }
    
        // Name & add new column
        printf("\nNew column's name:\n");
        printf("\nC%d: ", t->cols - 1);
        fflush(stdin);
        gets(t->cell[0][t->cols - 1]);
    
        for(i = 1; i < t->rows; ++i){
            printf("\nR%d C%d: ", i, t->cols - 1);
            fflush(stdin);
            gets(t->cell[i][t->cols - 1]);
        }
    }
    It seems to work now! Will keep testing!
    Last edited by beta3designs; 08-01-2011 at 09:35 AM.

  8. #8
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    This:
    Code:
    t->cell[i][t->cols]
    does not exist. The last element in an array is always n-1, not n.

  9. #9
    C <3er
    Join Date
    Jul 2011
    Posts
    46
    Yeah sorry I just changed that before you posted! lol
    And now it works as expected sooo problem solved and thank you very much!! I will have to change the gets and the fflush thing now...
    P.S. @tabstop do you think the design for this small project is alright for the purpose and knowing the reasoning I gave?
    Last edited by beta3designs; 08-01-2011 at 09:38 AM.

  10. #10
    C <3er
    Join Date
    Jul 2011
    Posts
    46
    Ok having problems now adding rows instead of column... seems I can't learn from my mistakes... u.u
    Now I'm trying to add a new row but I'm getting the same kind of error, here is what I have so far:
    Code:
    void add_row(table *t){
        int i;
    
        // Increase rows count
        ++(t->rows);
    
        t->cell = (char ***) realloc(t->cell, t->rows * sizeof(char **));
    
        for(i = 0; i < t->cols; ++i){
            t->cell[t->rows - 1][i] = (char *) malloc(NAME_MAX_LEN * sizeof(char));
            if(t->cell[t->rows - 1][i] == NULL){
                printf("\n\t\tERROR: Out of memory\n");
                printf("\n\t\tPress any key to exit...\n");
                getchar();
                exit(EXIT_FAILURE);
            }
        }
    
        for(i = 0; i < t->cols; ++i){
            printf("\nR%d C%d: ", t->rows - 1, i);
            fflush(stdin);
            gets(t->cell[t->rows - 1][i]);
        }
    }
    I tried to reallocate t->cell to one row more, then for this new row trying to allocate the space for the string for each column... anyone knows what's wrong with this?

  11. #11
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    You have to have something before you can use it. Before you can use t->cell[t->rows-1][anything], you have to acquire memory for that row to even exist. Your realloc gave you space to hold a pointer to the row; you then need to actually get a row.

    (And yes, a dynamic 2-D array isn't so bad. It might have been better, at the very beginning, to typedef char[NAME_MAX_LEN] to something like "field", so then we'd only be dealing with field** instead of char***. There wouldn't be any differences in the actual mechanics, but it's surprising how much that can help you thinking-wise.)

  12. #12
    C <3er
    Join Date
    Jul 2011
    Posts
    46
    Ok thank you very much, updated code is now:
    Code:
    void add_row(table *t){
        int i;
    
        // Increase rows count
        ++(t->rows);
    
        t->cell = (char ***) realloc(t->cell, t->rows * sizeof(char **));
        t->cell[t->rows - 1] = (char **) malloc(t->cols * sizeof(char *));
    
        for(i = 0; i < t->cols; ++i){
            t->cell[t->rows - 1][i] = (char *) malloc(NAME_MAX_LEN * sizeof(char));
            if(t->cell[t->rows - 1][i] == NULL){
                printf("\n\t\tERROR: Out of memory\n");
                printf("\n\t\tPress any key to exit...\n");
                getchar();
                exit(EXIT_FAILURE);
            }
        }
    
        for(i = 0; i < t->cols; ++i){
            printf("\nR%d C%d: ", t->rows - 1, i);
            fflush(stdin);
            gets(t->cell[t->rows - 1][i]);
        }
    }
    That's what you meant me to add right? :P

    (You mean a dynamic 3-D array not 2-D right? and thanks for the tip on the typedef thing, didn't think about it... anyways as you said at the very beginning now that everything is hard-coded... too much work to change everything lol)

  13. #13
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Despite seeing char***, it's not "really" a 3-D array; it's a 2-D array of char[] (or char*) -- all you have are rows and columns, right? -- which is why I suggested the typedef to make it clearer as to what it really is.

  14. #14
    C <3er
    Join Date
    Jul 2011
    Posts
    46
    Quote Originally Posted by tabstop View Post
    Despite seeing char***, it's not "really" a 3-D array;
    Aaah yeah I understand what you mean :P
    Good, my program now works as expected so unless someone wants to say something, topic solved.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Memory allocation/reallocation
    By magda3227 in forum C Programming
    Replies: 10
    Last Post: 07-04-2008, 03:27 PM
  2. Memory reallocation in C++
    By spank in forum C++ Programming
    Replies: 2
    Last Post: 08-08-2007, 09:56 AM
  3. Dynamic memory reallocation
    By Gravedigga in forum C++ Programming
    Replies: 6
    Last Post: 05-15-2005, 06:39 PM
  4. dynamic reallocation
    By ichijoji in forum Game Programming
    Replies: 4
    Last Post: 05-06-2004, 09:35 AM
  5. Dynamic array allocation and reallocation
    By purple in forum C Programming
    Replies: 13
    Last Post: 08-01-2002, 11:48 AM