454,605 Members | 1,391 Online Need help? Post your question and get tips & solutions from a community of 454,605 IT Pros & Developers. It's quick & easy.

# accessing a struct

 P: n/a Hi, What is the error in the code below? The output is: DEBUG: matrix.b is 2.000000 DEBUG: matrix->b is 0.000000 In other words, the struct is empty after it is passed to the solve_tridiag function. How can I fix this? I didn't see this in the FAQ, although I have the feeling that I'm missing something basic here. Many Thanks, Michael Goerz #include struct Tridiag{ // represents a tridiagonal matrix like this: // b1 c1 0 0 0 ... // a2 b2 c2 0 0 ... // 0 a3 b3 c3 0 ... // ... ... double *a; double *b; double *c; }; struct Tridiag create_matrix(){ struct Tridiag matrix; double b = { 2.0, 2.0, 2.0, 2.0, 2.0}; double a = { 0.0, -1.0, -1.0, -1.0, -1.0}; double c = {-1.0, -1.0, -1.0, -1.0, 0.0}; matrix.b = b; matrix.a = a; matrix.c = c; return matrix; } void solve_tridiag( struct Tridiag *matrix, double *r){ printf("DEBUG: matrix->b is %f\n", matrix->b); // ... } int main(){ double r[] = {0.0 , 1.0, 2.0, 3.0, 4.0}; struct Tridiag matrix = create_matrix(); printf("DEBUG: matrix.b is %f\n", matrix.b); solve_tridiag(&matrix, r); return 0; } Nov 11 '06 #1
4 Replies

 P: n/a Michael Goerz wrote: Hi, What is the error in the code below? The output is: DEBUG: matrix.b is 2.000000 DEBUG: matrix->b is 0.000000 In other words, the struct is empty after it is passed to the solve_tridiag function. How can I fix this? I didn't see this in the FAQ, although I have the feeling that I'm missing something basic here. Many Thanks, Michael Goerz #include struct Tridiag{ // represents a tridiagonal matrix like this: // b1 c1 0 0 0 ... // a2 b2 c2 0 0 ... // 0 a3 b3 c3 0 ... // ... ... double *a; double *b; double *c; }; struct Tridiag create_matrix(){ struct Tridiag matrix; double b = { 2.0, 2.0, 2.0, 2.0, 2.0}; double a = { 0.0, -1.0, -1.0, -1.0, -1.0}; double c = {-1.0, -1.0, -1.0, -1.0, 0.0}; matrix.b = b; matrix.a = a; matrix.c = c; return matrix; } So you saved the address of local arrays a, b and c onto data members of matrix. Do you expect that the data these arrays point to after the execution of this function will also be saved? DEBUG: matrix->b is 0.000000 void solve_tridiag( struct Tridiag *matrix, double *r){ printf("DEBUG: matrix->b is %f\n", matrix->b); // ... } int main(){ double r[] = {0.0 , 1.0, 2.0, 3.0, 4.0}; struct Tridiag matrix = create_matrix(); printf("DEBUG: matrix.b is %f\n", matrix.b); "DEBUG: matrix.b is 2.000000" Since you can access the saved data here, doesn't really means that this data will be there for ever. After you finished executing 'create_matrix()' function, the memory used by these arrays is up for grabs, your OS may use it as it needs it. solve_tridiag(&matrix, r); return 0; } I believe if you address these issues, your program should start behaving. Regards, Manish Nov 11 '06 #2

 P: n/a Michael Goerz b is 0.000000 In other words, the struct is empty after it is passed to the solve_tridiag function. How can I fix this? I didn't see this in the FAQ, although I have the feeling that I'm missing something basic here. #include struct Tridiag{ double *a; double *b; double *c; }; struct Tridiag create_matrix(){ struct Tridiag matrix; double b = { 2.0, 2.0, 2.0, 2.0, 2.0}; double a = { 0.0, -1.0, -1.0, -1.0, -1.0}; double c = {-1.0, -1.0, -1.0, -1.0, 0.0}; matrix.b = b; matrix.a = a; matrix.c = c; Now matrix.a, matrix.b and matrix.c are pointers to memory that is local to this function. And once the function has ended they point to memory you don't own anymore since the three arrays have gone out of scope. return matrix; } void solve_tridiag( struct Tridiag *matrix, double *r){ printf("DEBUG: matrix->b is %f\n", matrix->b); } int main(){ Better make that int main( void ) double r[] = {0.0 , 1.0, 2.0, 3.0, 4.0}; struct Tridiag matrix = create_matrix(); printf("DEBUG: matrix.b is %f\n", matrix.b); This only works by accident. Probably the data of the three arrays the elements of matrix point to still are undisturbed on the stack, so it may look as everything is fine, but you're just unlucky. If you would try the same program on a different machine it could al- ready give you an "unexpected" result here. solve_tridiag(&matrix, r); And now calling another function overwrites things on the stack and you finally find out about the errors of your way;-) Bugs where one uses memory that one doesn't own can be hard to find since it can look like nothing bad happened for a long time, only to result in a weird problem somewhere else, seemingly completely unrelated to where the original error was. return 0; } Regards, Jens -- \ Jens Thoms Toerring ___ jt@toerring.de \__________________________ http://toerring.de Nov 11 '06 #3

 P: n/a Michael Goerz wrote: Hi, What is the error in the code below? The output is: DEBUG: matrix.b is 2.000000 DEBUG: matrix->b is 0.000000 In other words, the struct is empty after it is passed to the solve_tridiag function. How can I fix this? I didn't see this in the FAQ, although I have the feeling that I'm missing something basic here. It's Question 7.5a, but somewhat disguised. The FAQ's example has a function returning a pointer value that points to one of the function's auto variables, and since the variable ceases to exist when the function returns the pointer is no good to the caller. You're not doing exactly that, but ... #include struct Tridiag{ // represents a tridiagonal matrix like this: // b1 c1 0 0 0 ... // a2 b2 c2 0 0 ... // 0 a3 b3 c3 0 ... // ... ... double *a; double *b; double *c; }; struct Tridiag create_matrix(){ struct Tridiag matrix; double b = { 2.0, 2.0, 2.0, 2.0, 2.0}; double a = { 0.0, -1.0, -1.0, -1.0, -1.0}; double c = {-1.0, -1.0, -1.0, -1.0, 0.0}; All of b, a, c will cease to exist when create_matrix() returns, just as in the FAQ's example. matrix.b = b; matrix.a = a; matrix.c = c; return matrix; There's nothing wrong with returning the struct value `matrix', but matrix.b, matrix.a, matrix.c are pointing to b, a, c, which are about to expire ... } Solution: You need the struct elements to point to storage that will survive after create_matrix() has been and gone, and for as long as you still need the values. One possibility is to use static storage, as illustrated in the FAQ. Another is to call malloc() to obtain dynamic storage that will hold the values provided by create_matrix(); it would be a good idea to write a companion destroy_matrix() to free() the dynamic memory when you're done with it. Hard to say which approach is more suitable; in the "toy" program you've shown static storage is easier, but I imagine you have more involved applications in mind. -- Eric Sosman es*****@acm-dot-org.invalid Nov 11 '06 #4

 P: n/a Hello Michael, What is the error in the code below? The output is: DEBUG: matrix.b is 2.000000 DEBUG: matrix->b is 0.000000 In other words, the struct is empty after it is passed to the solve_tridiag function. How can I fix this? I didn't see this in the FAQ, although I have the feeling that I'm missing something basic here. struct Tridiag create_matrix(){ struct Tridiag matrix; double b = { 2.0, 2.0, 2.0, 2.0, 2.0}; double a = { 0.0, -1.0, -1.0, -1.0, -1.0}; double c = {-1.0, -1.0, -1.0, -1.0, 0.0}; matrix.b = b; matrix.a = a; matrix.c = c; return matrix; } Here is your problem. The pointer matrix.b,matrix.a,matrix.c of your Tridiag structure point to the *local* variables (ie. located on the stack) b,a,c resp. The life of those variables is only limited to the function create_matrix(). And soon as the function returns, the values are undefined. That's actually the effect your are seeing. You can fix your code as follow. You can declare the variable b,a,c in create_matrix() as static. Or you can allocate with malloc()/calloc() enough room for matrix.b,matrix.a,matrix.c and you copy the contents of b,a,c as appropriate with memcpy(). HTH, Loic. Nov 11 '06 #5

### This discussion thread is closed

Replies have been disabled for this discussion. 