freeing a matix

Discussion in 'C Programming' started by Michael Goerz, Dec 1, 2006.

  1. Hi,

    how can I free a matrix that was created with this function:

    double **my_matrix(long number_of_rows, long number_of_columns){
    double **matrix;
    matrix = calloc(number_of_rows, sizeof(double *));
    int i;
    for (i = 0; i < number_of_rows; i++){
    matrix = calloc(number_of_columns, sizeof(double));
    }
    return matrix;
    }


    My guess was this,

    void my_free_matrix(double **m, long number_of_rows, long
    number_of_columns){
    int row;
    for (row = 0; row < number_of_rows; row++){
    free(m[row]);
    }
    free(m);
    }

    but it fails with "*** glibc detected *** double free or corruption
    (out): 0xbfbbaa58 ***"

    Many Thanks,
    Michael Goerz
    Michael Goerz, Dec 1, 2006
    #1
    1. Advertising

  2. Michael Goerz

    Bill Medland Guest

    Michael Goerz wrote:

    > Hi,
    >
    > how can I free a matrix that was created with this function:
    >
    > double **my_matrix(long number_of_rows, long number_of_columns){
    > double **matrix;
    > matrix = calloc(number_of_rows, sizeof(double *));
    > int i;
    > for (i = 0; i < number_of_rows; i++){
    > matrix = calloc(number_of_columns, sizeof(double));
    > }
    > return matrix;
    > }
    >
    >
    > My guess was this,
    >
    > void my_free_matrix(double **m, long number_of_rows, long
    > number_of_columns){
    > int row;
    > for (row = 0; row < number_of_rows; row++){
    > free(m[row]);
    > }
    > free(m);
    > }
    >
    > but it fails with "*** glibc detected *** double free or corruption
    > (out): 0xbfbbaa58 ***"
    >
    > Many Thanks,
    > Michael Goerz

    Looks right to me. Have you tried running under a debugger to watch it?
    Possibly the number of rows disagrees between the allocation and the
    release?
    --
    Bill Medland
    Bill Medland, Dec 1, 2006
    #2
    1. Advertising

  3. Bill Medland wrote:
    >> void my_free_matrix(double **m, long number_of_rows, long
    >> number_of_columns){
    >> int row;
    >> for (row = 0; row < number_of_rows; row++){
    >> free(m[row]);
    >> }
    >> free(m);
    >> }
    >>
    >> but it fails with "*** glibc detected *** double free or corruption
    >> (out): 0xbfbbaa58 ***"
    >>

    > Looks right to me. Have you tried running under a debugger to watch it?
    > Possibly the number of rows disagrees between the allocation and the
    > release?


    Yeah, I think the problem was that I put a static array in one of the
    matrix rows. I guess I just can't do that, can I?

    int main(){
    double **m = my_matrix(4,3); // create a 4x3 matrix
    m[0][1] = 5.0;
    double row2[] = {1.0, 2.0, 3.0, 4.0};
    m[1] = row2; // leave this out, and it doesn't crash
    my_free_matrix(m, 4, 3);
    return 0;
    }
    Michael Goerz, Dec 1, 2006
    #3
  4. Michael Goerz

    Bill Medland Guest

    Michael Goerz wrote:

    > Bill Medland wrote:
    >>> void my_free_matrix(double **m, long number_of_rows, long
    >>> number_of_columns){
    >>> int row;
    >>> for (row = 0; row < number_of_rows; row++){
    >>> free(m[row]);
    >>> }
    >>> free(m);
    >>> }
    >>>
    >>> but it fails with "*** glibc detected *** double free or corruption
    >>> (out): 0xbfbbaa58 ***"
    >>>

    >> Looks right to me. Have you tried running under a debugger to watch it?
    >> Possibly the number of rows disagrees between the allocation and the
    >> release?

    >
    > Yeah, I think the problem was that I put a static array in one of the
    > matrix rows. I guess I just can't do that, can I?
    >


    Um, No, you can't :)

    > int main(){
    > double **m = my_matrix(4,3); // create a 4x3 matrix
    > m[0][1] = 5.0;
    > double row2[] = {1.0, 2.0, 3.0, 4.0};
    > m[1] = row2; // leave this out, and it doesn't crash
    > my_free_matrix(m, 4, 3);
    > return 0;
    > }


    Basically with C you need to understand pointers and what they point to.

    m is a pointer. It points to the first element of the array. Each element
    of that array is itself a pointer to the first element of an array.

    What you did was to allocate all the space you needed and then change the
    pointer that was the second pointer in the top level array.

    Then when you went to deallocate the matrix two things happened;
    a. my_free_matrix tried to release that array on the stack (which it didn't
    like doing)
    b. my_free_matrix did NOT try and release the space you allocated (because
    you dropped the pointer to it).

    What you should have done is copy the elements of row2 into the space
    pointed to by m[1].

    Hopefully that helps.

    --
    Bill Medland
    Bill Medland, Dec 1, 2006
    #4
  5. Michael Goerz

    Simon Biber Guest

    Michael Goerz wrote:
    > Bill Medland wrote:
    >>> void my_free_matrix(double **m, long number_of_rows, long
    >>> number_of_columns){
    >>> int row;
    >>> for (row = 0; row < number_of_rows; row++){
    >>> free(m[row]);
    >>> }
    >>> free(m);
    >>> }
    >>>
    >>> but it fails with "*** glibc detected *** double free or corruption
    >>> (out): 0xbfbbaa58 ***"
    >>>

    >> Looks right to me. Have you tried running under a debugger to watch it?
    >> Possibly the number of rows disagrees between the allocation and the
    >> release?

    >
    > Yeah, I think the problem was that I put a static array in one of the
    > matrix rows. I guess I just can't do that, can I?


    You can do that, but you need to keep track of which rows need freeing
    and which don't.

    > int main(){
    > double **m = my_matrix(4,3); // create a 4x3 matrix
    > m[0][1] = 5.0;
    > double row2[] = {1.0, 2.0, 3.0, 4.0};
    > m[1] = row2; // leave this out, and it doesn't crash
    > my_free_matrix(m, 4, 3);
    > return 0;
    > }


    Try this:

    void my_free_matrix(double **m, long number_of_rows,
    long number_of_columns, char *dont_free) {
    int row;
    for (row = 0; row < number_of_rows; row++){
    if(!dont_free[row]) free(m[row]);
    }
    free(m);
    }

    int main() {
    char *dont_free = calloc(4, sizeof *dont_free);
    double **m = my_matrix(4, 3);
    m[0][1] = 5.0;
    double row2[] = {1.0, 2.0, 3.0};
    dont_free[1] = 1; // register row 1 as no free
    free(m[1]); // do free here to avoid mem leak
    m[1] = row2;
    my_free_matrix(m, 4, 3, dont_free);
    free(dont_free);
    return 0;
    }

    Note that this code, and your my_matrix function should really check for
    failure of calloc; it returns a null pointer if the memory is not available.

    --
    Simon.
    Simon Biber, Dec 2, 2006
    #5
  6. I'd write this as

    double ** my_matrix(long number_of_rows, long number_of_columns){
    double ** ptr;
    double * temp;
    long i;

    /* All data is in a single malloc. First are the pointers, then the
    doubles */
    ptr = (double **)malloc(number_of_rows * sizeof(double *) +
    number_of_rows * number_of_columns * sizeof(double));

    temp = (double *)&ptr[number_of_rows]; /* get a pointer to where the
    doubles are stored */

    for (i = 0; i < number_of_rows; i++)
    {
    ptr = &temp[i*number_of_columns];
    }

    return ptr;
    }


    Then it only takes a single free to delete it.
    And you can insert rows with an assignment to a static array without
    error.


    Michael Goerz wrote:
    > Hi,
    >
    > how can I free a matrix that was created with this function:
    >
    > double **my_matrix(long number_of_rows, long number_of_columns){
    > double **matrix;
    > matrix = calloc(number_of_rows, sizeof(double *));
    > int i;
    > for (i = 0; i < number_of_rows; i++){
    > matrix = calloc(number_of_columns, sizeof(double));
    > }
    > return matrix;
    > }
    >
    >
    > My guess was this,
    >
    > void my_free_matrix(double **m, long number_of_rows, long
    > number_of_columns){
    > int row;
    > for (row = 0; row < number_of_rows; row++){
    > free(m[row]);
    > }
    > free(m);
    > }
    >
    > but it fails with "*** glibc detected *** double free or corruption
    > (out): 0xbfbbaa58 ***"
    >
    > Many Thanks,
    > Michael Goerz
    Samuel Stearley, Dec 3, 2006
    #6
  7. I'd write this as

    double ** my_matrix(long number_of_rows, long number_of_columns){
    double ** ptr;
    double * temp;
    long i;

    /* All data is in a single malloc. First are the pointers, then the
    doubles */
    ptr = (double **)malloc(number_of_rows * sizeof(double *) +
    number_of_rows * number_of_columns * sizeof(double));

    temp = (double *)&ptr[number_of_rows]; /* get a pointer to where the
    doubles are stored */

    for (i = 0; i < number_of_rows; i++)
    {
    ptr = &temp[i*number_of_columns];
    }

    return ptr;
    }


    Then it only takes a single free to delete it.
    And you can insert rows with an assignment to a static array without
    error.


    Michael Goerz wrote:
    > Hi,
    >
    > how can I free a matrix that was created with this function:
    >
    > double **my_matrix(long number_of_rows, long number_of_columns){
    > double **matrix;
    > matrix = calloc(number_of_rows, sizeof(double *));
    > int i;
    > for (i = 0; i < number_of_rows; i++){
    > matrix = calloc(number_of_columns, sizeof(double));
    > }
    > return matrix;
    > }
    >
    >
    > My guess was this,
    >
    > void my_free_matrix(double **m, long number_of_rows, long
    > number_of_columns){
    > int row;
    > for (row = 0; row < number_of_rows; row++){
    > free(m[row]);
    > }
    > free(m);
    > }
    >
    > but it fails with "*** glibc detected *** double free or corruption
    > (out): 0xbfbbaa58 ***"
    >
    > Many Thanks,
    > Michael Goerz
    Samuel Stearley, Dec 3, 2006
    #7
  8. On 2 Dec 2006 18:39:31 -0800, "Samuel Stearley" <>
    wrote:

    >I'd write this as
    >
    >double ** my_matrix(long number_of_rows, long number_of_columns){
    > double ** ptr;
    > double * temp;
    > long i;
    >
    > /* All data is in a single malloc. First are the pointers, then the
    >doubles */
    > ptr = (double **)malloc(number_of_rows * sizeof(double *) +
    >number_of_rows * number_of_columns * sizeof(double));
    >
    > temp = (double *)&ptr[number_of_rows]; /* get a pointer to where the
    >doubles are stored */


    On a system where sizeof(double*) is 4, sizeof(double) is 8, and each
    is required to be aligned to a multiple of its size, this is
    guaranteed to fail when number_of_rows is odd.


    Remove del for email
    Barry Schwarz, Dec 3, 2006
    #8
  9. Oops

    double ** my_matrix(long number_of_rows, long number_of_columns){
    double ** ptr;
    double * temp;
    long alignment;
    long i;

    /* All data is in a single malloc. First are the pointers, then the
    doubles */
    alignment = number_of_rows &1;
    ptr = (double **)malloc( (number_of_rows + alignment) * sizeof(double
    *) +
    number_of_rows * number_of_columns * sizeof(double));

    temp = (double *)&ptr[number_of_rows + alignment]; /* get a pointer to
    where the
    doubles are stored */

    for (i = 0; i < number_of_rows; i++)
    {
    ptr = &temp[i*number_of_columns];
    }

    return ptr;

    }




    Barry Schwarz wrote:
    > On 2 Dec 2006 18:39:31 -0800, "Samuel Stearley" <>
    > wrote:
    >
    > >I'd write this as
    > >
    > >double ** my_matrix(long number_of_rows, long number_of_columns){
    > > double ** ptr;
    > > double * temp;
    > > long i;
    > >
    > > /* All data is in a single malloc. First are the pointers, then the
    > >doubles */
    > > ptr = (double **)malloc(number_of_rows * sizeof(double *) +
    > >number_of_rows * number_of_columns * sizeof(double));
    > >
    > > temp = (double *)&ptr[number_of_rows]; /* get a pointer to where the
    > >doubles are stored */

    >
    > On a system where sizeof(double*) is 4, sizeof(double) is 8, and each
    > is required to be aligned to a multiple of its size, this is
    > guaranteed to fail when number_of_rows is odd.
    >
    >
    > Remove del for email
    Samuel Stearley, Dec 3, 2006
    #9
  10. Michael Goerz

    pete Guest

    Samuel Stearley wrote:
    >
    > Oops
    >
    > double ** my_matrix(long number_of_rows, long number_of_columns){


    Are we still doing this problem?

    /* BEGIN new.c */

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

    double **my_matrix(unsigned rows, unsigned columns);
    void my_free_matrix(double **m, unsigned rows);
    void init_matrix(double **m, unsigned rows, unsigned columns);
    void show_matrix(double **m, unsigned rows, unsigned columns);

    int main(void)
    {
    unsigned rows = 5;
    unsigned columns = 7;
    double **matrix;

    matrix = my_matrix(rows, columns);
    if (matrix != NULL) {
    init_matrix(matrix, rows, columns);
    show_matrix(matrix, rows, columns);
    my_free_matrix(matrix, rows);
    puts("\nThe matrix has been freed.");
    } else {
    puts("matrix == NULL");
    }
    return 0;
    }

    double **my_matrix(unsigned rows, unsigned columns)
    {
    double **matrix;
    unsigned i;

    matrix = calloc(rows, sizeof *matrix);
    if (matrix != NULL) {
    for (i = 0; i != rows; ++i) {
    matrix = calloc(columns, sizeof *matrix);
    if (matrix == NULL) {
    my_free_matrix(matrix, i);
    matrix = NULL;
    break;
    }
    }
    }
    return matrix;
    }

    void my_free_matrix(double **m, unsigned rows)
    {
    while (rows-- != 0) {
    free(m[rows]);
    }
    free(m);
    }

    void init_matrix(double **m, unsigned rows, unsigned columns)
    {
    unsigned r, c;

    for (r = 0; r != rows; ++r) {
    for (c = 0; c != columns; ++c) {
    m[r][c] = r + c + 0.5;
    }
    }
    }

    void show_matrix(double **m, unsigned rows, unsigned columns)
    {
    unsigned r, c;

    for (r = 0; r != rows; ++r) {
    for (c = 0; c != columns; ++c) {
    printf("%f ", m[r][c]);
    }
    putchar('\n');
    }
    }

    /* END new.c */




    --
    pete
    pete, Dec 4, 2006
    #10
  11. On 3 Dec 2006 15:49:50 -0800, "Samuel Stearley" <>
    wrote:

    >Oops
    >
    >double ** my_matrix(long number_of_rows, long number_of_columns){
    > double ** ptr;
    > double * temp;
    > long alignment;
    > long i;
    >
    > /* All data is in a single malloc. First are the pointers, then the
    >doubles */
    > alignment = number_of_rows &1;
    > ptr = (double **)malloc( (number_of_rows + alignment) * sizeof(double
    >*) +
    >number_of_rows * number_of_columns * sizeof(double));


    This probably solves the problem for when sizeof(double) is twice the
    sizeof(double*) but now when the ratio is four (4 bytes for a pointer
    and 16 bytes for a double). It just introduces a thoroughly
    unnecessary lack of portability.

    >
    > temp = (double *)&ptr[number_of_rows + alignment]; /* get a pointer to
    >where the
    >doubles are stored */
    >
    > for (i = 0; i < number_of_rows; i++)
    > {
    > ptr = &temp[i*number_of_columns];
    > }
    >
    > return ptr;
    >
    >}
    >
    >
    >
    >
    >Barry Schwarz wrote:
    >> On 2 Dec 2006 18:39:31 -0800, "Samuel Stearley" <>
    >> wrote:
    >>
    >> >I'd write this as
    >> >
    >> >double ** my_matrix(long number_of_rows, long number_of_columns){
    >> > double ** ptr;
    >> > double * temp;
    >> > long i;
    >> >
    >> > /* All data is in a single malloc. First are the pointers, then the
    >> >doubles */
    >> > ptr = (double **)malloc(number_of_rows * sizeof(double *) +
    >> >number_of_rows * number_of_columns * sizeof(double));
    >> >
    >> > temp = (double *)&ptr[number_of_rows]; /* get a pointer to where the
    >> >doubles are stored */

    >>
    >> On a system where sizeof(double*) is 4, sizeof(double) is 8, and each
    >> is required to be aligned to a multiple of its size, this is
    >> guaranteed to fail when number_of_rows is odd.
    >>
    >>
    >> Remove del for email



    Remove del for email
    Barry Schwarz, Dec 4, 2006
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Gordon Beaton

    Freeing object created in JNI code?

    Gordon Beaton, Oct 27, 2003, in forum: Java
    Replies:
    1
    Views:
    320
    Tony Tang
    Oct 27, 2003
  2. Rajesh.Rapaka

    freeing memory

    Rajesh.Rapaka, Apr 20, 2005, in forum: Java
    Replies:
    17
    Views:
    2,828
    Eric Sosman
    Apr 21, 2005
  3. Harald Kirsch

    freeing memory

    Harald Kirsch, Apr 22, 2005, in forum: Java
    Replies:
    0
    Views:
    421
    Harald Kirsch
    Apr 22, 2005
  4. Stefan Ram

    Freeing Algorithms

    Stefan Ram, Mar 18, 2006, in forum: Java
    Replies:
    32
    Views:
    1,073
    Oliver Wong
    Mar 21, 2006
  5. Alexander
    Replies:
    11
    Views:
    803
    Richard Damon
    Sep 30, 2011
Loading...

Share This Page