This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Double pointer usage "freeze"

Hello!

Iam currently working on a project with the XC2785X-104F Controller, uVision 4 and Keil C166 Compiler.
Within my code i have to work with matrices and several matrix calculations. Therefor iam working with double pointers, structs and 2 dimensional arrays.

######################### Code snippet ###################

#################################### matrix struct (incl col,row)

typedef struct { int row; int col; } MATHEAD;

typedef struct { MATHEAD head; double *matrix; } MATBODY;

typedef double **MATRIX;

#define Mathead(a) ((MATHEAD *)((MATHEAD *)(a) - 1))
#define MatRow(a) (Mathead(a)->row)
#define MatCol(a) (Mathead(a)->col)

############################################# struct to work with

typedef struct { MATRIX A, B, C; double var;

}structure;

############################################ func to "create" matrices

MATRIX mat_creat( row, col, type )
int row, col, type;
{ MATRIX A;

if ((A =_mat_creat( row, col )) != NULL) { return (mat_fill(A, type)); } else return (NULL);

return (A);
}

MATRIX _mat_creat( row, col )
int row, col;
{ MATBODY *mat; int i;

if ((mat = (MATBODY *)malloc( sizeof(MATHEAD) + sizeof(double *) * row)) == NULL) return NULL;//(mat_error( MAT_MALLOC ));

for (i=0; i<row; i++) { if ((*((double **)(&mat->matrix) + i) = (double *)malloc(sizeof(double) * col)) == NULL) return NULL;//(mat_error( MAT_MALLOC )); }

mat->head.row = row; mat->head.col = col;

return (&(mat->matrix)); //(& )
}

########################### main.c

structure test1;

// value for var
test1.var = 1.234;

// send data via uart to terminal
send_uart(test1.var); // works fine

// create a 2x1 matrix with unknown data
test1.A = mat_creat(2,1,UNDEFINED);

// fill matrix with values
test1.A[0][0] = 0x00; // <--------- causes uC-freeze at this point

// send data via uart to terminal
send_uart(test1.A[0][0]); // is not delivered
send_uart("TEST\n"); // is not delivered

########################## END Code snippet ##############################

If i comment that line out (// test1.A[0][0] = 0x00;) everything works fine.
If not, there is no error nor a warning from the compiler. Just a freeze on the uC.

In my eyes the error lies in the usage of the double pointer, but i can't find the mistake. Also tried the same code in eclipse with gnu c compiler and everything worked fine...

Does anybody know where the problem is?
Did anyone make similar experiences??

I hope someone can help me!

thank you!

Bye,
Josh

  • I don't think anyone likes to try to read your code, since you somehow forgot to tag the code as clearly described directly above the message input box.

    But mat_creat() may return NULL. Why don't you find it important to check if you do have a valid allocation before you try the pointer indirection? Or did you expect the compiler to warn about runtime errors too?

  • Sorry for not tagging the code the right way (somehow i did not see it). I added the correct marked lines below

    @author: Thanks for your fast reply. Right, iam not checking for a valid allocation in this example here. I don't think that's the point but will try it as soon as being back to my office :)

    Go ahead with creative ideas folks!

    thx,
    Josh

    ######################### Code snippet ###################
    
    #################################### matrix struct (incl col,row)
    
    typedef struct { int row; int col; } MATHEAD;
    
    typedef struct { MATHEAD head; double *matrix; } MATBODY;
    
    typedef double **MATRIX;
    
    #define Mathead(a) ((MATHEAD *)((MATHEAD *)(a) - 1))
    #define MatRow(a) (Mathead(a)->row)
    #define MatCol(a) (Mathead(a)->col)
    
    ############################################# struct to work with
    
    typedef struct { MATRIX A, B, C; double var;
    
    }structure;
    
    ############################################ func to "create" matrices
    
    MATRIX mat_creat( row, col, type )
    int row, col, type;
    { MATRIX A;
    
    if ((A =_mat_creat( row, col )) != NULL) { return (mat_fill(A, type)); } else return (NULL);
    
    return (A);
    }
    
    MATRIX _mat_creat( row, col )
    int row, col;
    { MATBODY *mat; int i;
    
    if ((mat = (MATBODY *)malloc( sizeof(MATHEAD) + sizeof(double *) * row)) == NULL) return NULL;//(mat_error( MAT_MALLOC ));
    
    for (i=0; i<row; i++) { if ((*((double **)(&mat->matrix) + i) = (double *)malloc(sizeof(double) * col)) == NULL) return NULL;//(mat_error( MAT_MALLOC )); }
    
    mat->head.row = row; mat->head.col = col;
    
    return (&(mat->matrix)); //(& )
    }
    
    ########################### main.c
    
    structure test1;
    
    // value for var
    test1.var = 1.234;
    
    // send data via uart to terminal
    send_uart(test1.var); // works fine
    
    // create a 2x1 matrix with unknown data
    test1.A = mat_creat(2,1,UNDEFINED);
    
    // fill matrix with values
    test1.A[0][0] = 0x00; // <--------- causes uC-freeze at this point
    
    // send data via uart to terminal
    send_uart(test1.A[0][0]); // is not delivered
    send_uart("TEST\n"); // is not delivered
    
    ########################## END Code snippet ##############################
    

  • Right, iam not checking for a valid allocation in this example here. I don't think that's the point

    Oh, I think this could well be the point. You didn't by any chance forget to initialize the heap for dynamic memory allocation, did you?

    http://www.keil.com/support/man/docs/c166/c166_init_mempool.htm

  • I added the correct marked lines below

    Too bad you didn't think of putting back in some readability, though. You apparently just copied the already broken formatting of your original posting and put the "pre" tag around that. Did you even look at the resulting mess before submitting?

    That said, let me point out that that is rather spectacularly messy code. For starters you went against pretty much every single existing convention on naming macros, types and variables. And what on earth makes you use old-style (non-prototyped) function definitions in this day and age?

    Next you're putting entirely too many casts into that code. To a very good approximation, every pointer cast in a C program is either superfluous or wrong.

    And half of those places where you felt the need for a pointer caused are caused by trying to be cleverer than does you any good. Get rid of the Mathead macro and all its uses, and of typedef MATRIX. Use MATBODY instead. Hiding the actual structure of your data behind mangled pointers and macros isn't half as good idea as you think.

  • To a very good approximation, every pointer cast in a C program is either superfluous or wrong.
    

    Your alter ego isn't Dr Jameson by any chance? You sound much like my first lecturer of software engineering who stated that no function should have more than three lines of code.

    He's still a lecturer. We went on to write real code.

  • "To a very good approximation, every pointer cast in a C program is either superfluous or wrong"

    Having just had to deal with some code where pointer casts were wrong and were masking errors, I would very much agree with that approximation!

    It is, of course, just an approximation - there are a few cases where pointer casts are warranted. But they are certainly the exception rather than the rule.

  • To a very good approximation, every pointer cast in a C program is either superfluous or wrong
    

    My car had a problem recently so I took it to the garage. The problem was caused by a nut not being correctly tightened. Why wasn't it correctly tightened? Simple, it was the wrong type.

    Probably best to ban all nuts.

  • But how often does that happen?

    Pointer mis-casting, on the other hand, is very common...

  • Most type casts gets added because one of:
    - the developer wants to "explain" the code by adding type casts as some form of comment to tell what data type (he thinks) the variable has.
    - the developer gets compilation errors and don't completely understand the pointer logic so he adds different variants of type casts until the compiler doesn't complain anymore.

    Why can't someone release a compiler that after the third "trial-and-error" typecast found introduces a 24 hour compilation lockdown while requiring the developer to get a good C/C++ book and read up on the subject?

  • Which certainly looks like the case here:

    *((double **)(&mat->matrix) + i)
    

  • Hey folks!

    thanks for all the (more or less usefull) answers. Especially to Andrew!!
    The problem seems to be solved now.
    It was not a NULL returning from the mat_creat function, moreover it was the missing init_mempool function which initializes the memory management routines.
    Yet i do not really understand how to use this func the right way.

    - Do i have to call the init_mempool(xxx) only once to reserve the memory for all my matrices?
    or
    - Do i have to call the func everytime i want memory reserved for a single (new created) matrix

    I've read the article in the User Guide: but it confused me somehow
    ... Call the init_mempool function only once at the beginning of your program ...
    otherwise it is used different in that tst_init_mempool function..

    So far, iam sorry to hear of some "noobish" errors in my code - i do not really have good programming skills and, unfortunately, not the time to enhance them.

  • Do i have to call the init_mempool(xxx) only once to reserve the memory for all my matrices?

    Exactly.

    i do not really have good programming skills and, unfortunately, not the time to enhance them.

    If you only need to get the program running and code readability and maintainability is not a concern, then simply ignore the criticism.

  • "... and, unfortunately, not the time to enhance them"

    But you have time to deal, like this, with the consequences?!

    Which is the better use of time:

    1. Throwing something together in a day, then spending a week sorting out the mess;

    2. Taking a week to learn how to do it properly, then spending a day getting it right first time.

    Your call!

  • IF this is a school project then, surely, the object of the exercise is to learn those skills?

    If it's a commercial project, wouldn't it be more appropriate to hire someone who does have the required skills?

  • My car had a problem recently so I took it to the garage. The problem was caused by a nut not being correctly tightened. Why wasn't it correctly tightened? Simple, it was the wrong type.

    Probably best to ban all nuts.

    Oh my, dude, are you in way over your head.

    First you thought you were qualified to insult other people's contributions without so much a hint of an argument of your own. I was going to let that pass as the usual childish nonsense of an anonymous coward.

    But that apparently wasn't enough for you. So you had to go and remove any remaining doubt and prove that you don't even understand the problem, much less qualify to judge advice about it, by completely missing the point with your supposed analogy above.

    You hardly deserve it, but for the benefit of other readers, I'll drop you a hint anyway: in a car analogy, the equivalent of those pointer casts would rather be chewing gum used to patch various gaping holes all across the car's critical systems.