473,397 Members | 2,077 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,397 software developers and data experts.

generic type, tree

hi, I having some problem with a void * and tree structure.
i am sure tha my fuction make tree is ok, but my fuction print return
adress instead of values.

Main :

int main()
{
node *n = init(5);
affiche(n);
return 0;
}

structure :

typedef struct node
{
void *value;
struct node* right;
struct node* left;
}node;

init :

node* init(int h)
{
if(h == 0)
return NULL;
int v = 1;
node *n = malloc(sizeof(node));
n->value = &v;
printf("->%d \t", *((int*)n->value));
n->right = init(h-1);
n->left = init(h-1);

return n;
}
print :
void affiche(node *n)
{
if(n != NULL)
{
int *v = (int*)n->value;
affiche(n->left);
printf("-->%d \t",*v);
affiche(n->right);

}
}

the problem is not in the fuction init, because the fuction printf
return good values.
i think it was in the fuction "affiche"
please help me, thanks
Jun 27 '08 #1
7 1472
al************@gmail.com wrote:
hi, I having some problem with a void * and tree structure.
i am sure tha my fuction make tree is ok, but my fuction print return
adress instead of values.
Main :
int main()
{
node *n = init(5);
affiche(n);
return 0;
}
structure :
typedef struct node
{
void *value;
struct node* right;
struct node* left;
}node;
init :
node* init(int h)
{
if(h == 0)
return NULL;
int v = 1;
node *n = malloc(sizeof(node));
n->value = &v;
Here you have a bad problem. What you store in the 'value' member
is a pointer to a variable that vanishes the moment you return
from this function. So any accesses to the 'value' member made
once you have returned invokes undefined behaviour and what
'value' points to rather likely has been overwritten by some
other value.

The only way to avoid that would be

int *v = malloc( sizeof *v );
*v = 1;
n->value = v;

since only that will give you a pointer to memory that you
still "own" after you returned from the function and will
keep the value you wrote to it.
printf("->%d \t", *((int*)n->value));
n->right = init(h-1);
n->left = init(h-1);
return n;
}
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
Jun 27 '08 #2
On 18 May 2008 at 10:46, Jens Thoms Toerring wrote:
al************@gmail.com wrote:
> int v = 1;
node *n = malloc(sizeof(node));
n->value = &v;

Here you have a bad problem. What you store in the 'value' member
is a pointer to a variable that vanishes the moment you return
from this function.
You're right, but perhaps it will also be helpful to mention to the OP
that tracking down such bugs is very easy using the valgrind tool, which
will pick up invalid memory accesses like this. (This is just in case
the OP isn't a preternaturally talented programmer like all the clc
regulars, who as we know have no need for debugging tools besides their
eyes.)

Jun 27 '08 #3
Antoninus Twink <no****@nospam.invalidwrites:
On 18 May 2008 at 10:46, Jens Thoms Toerring wrote:
>al************@gmail.com wrote:
>> int v = 1;
node *n = malloc(sizeof(node));
n->value = &v;

Here you have a bad problem. What you store in the 'value' member
is a pointer to a variable that vanishes the moment you return
from this function.

You're right, but perhaps it will also be helpful to mention to the OP
that tracking down such bugs is very easy using the valgrind tool, which
will pick up invalid memory accesses like this. (This is just in case
the OP isn't a preternaturally talented programmer like all the clc
regulars, who as we know have no need for debugging tools besides their
eyes.)
If the OP is using Linux (or Windows too I think) then splint is also
quite good. I got the link from this group I think.

Jun 27 '08 #4
Eligiusz Narutowicz <el*************@hotmail.comwrote:
Antoninus Twink <no****@nospam.invalidwrites:
On 18 May 2008 at 10:46, Jens Thoms Toerring wrote:
al************@gmail.com wrote:
int v = 1;
node *n = malloc(sizeof(node));
n->value = &v;

Here you have a bad problem. What you store in the 'value' member
is a pointer to a variable that vanishes the moment you return
from this function.
You're right, but perhaps it will also be helpful to mention to the OP
that tracking down such bugs is very easy using the valgrind tool, which
will pick up invalid memory accesses like this. (This is just in case
the OP isn't a preternaturally talented programmer like all the clc
regulars, who as we know have no need for debugging tools besides their
eyes.)
If the OP is using Linux (or Windows too I think) then splint is also
quite good. I got the link from this group I think.
While splint indeed gives you some hint at what's going wrong
(alas in a way that probably will make it hard for the OP to
grasp) using valgrind seems to me like looking for your mis-
placed keys with a microscope. All it tells you is something
about an invalid read in the affiche() function, rather likely
just reinforcing the OP in the wrong belive that there would
be something wrong with this function and not helping at all
in finding the real reason for the problem. I would recommend
to use valgrind (or similar memory debuggers) only as a last
resort and instead to learn to avoid such mistakes since val-
grind can only detect the results of those mistakes, not the
mistakes themselves.
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
Jun 27 '08 #5
On May 18, 2:50*am, alternative...@gmail.com wrote:
hi, I having some problem with a void * and tree structure.
i am sure tha my fuction make tree is ok, but my fuction print return
adress instead of values.

Main :

int main()
{
* * * * node *n = init(5);
This should have produced a diagnostic. There is no prototype in
scope for init so the compiler is obligated to assume it returns an
int. There is no implicit conversion between int a pointer to node.
Since init does not return an int, you also have undefined behavior.

It doesn't help that node is an unknown type at this point also.

* * * * affiche(n);
* * * * return 0;

}

structure :

typedef struct node
{
* * * * void *value;
* * * * struct node* right;
* * * * struct node* left;

}node;

init :

node* init(int h)
{
* * * * if(h == 0)
* * * * * * * * return NULL;
* * * * int v = 1;
* * * * node *n = malloc(sizeof(node));
No prototype for malloc either causing the same problems.
* * * * n->value = &v;
v is an automatic variable. It will cease to exist when init returns
to main. Once that happens, the value in n->value becomes
indeterminate and any attempt to evaluate it for any purpose causes
undefined behavior.
* * * * printf("->%d \t", *((int*)n->value));
* * * * n->right = init(h-1);
* * * * n->left = init(h-1);

* * * * return n;}

print :
void affiche(node *n)
{
* * * * if(n != NULL)
* * * * {
* * * * * * * * int *v = (int*)n->value;
Here is the undefined behavior mentioned above.
* * * * * * * * affiche(n->left);
* * * * * * * * printf("-->%d \t",*v);
* * * * * * * * affiche(n->right);

* * * * }

}

the problem is not in the fuction init, because the fuction printf
return good values.
One of the worst manifestations of undefined behavior is to appear to
do what is expected. Your design for init is faulty and is the cause
of at least some of the problems you are experiencing. If you told us
what those problems were, we might be able to offer better advice.
i think it was in the fuction "affiche"
The undefined behavior occurs in affiche because of the poor design of
init.
Jun 27 '08 #6
On May 18, 4:54 pm, j...@toerring.de (Jens Thoms Toerring) wrote:
Eligiusz Narutowicz <eligiuszdotn...@hotmail.comwrote:
Antoninus Twink <nos...@nospam.invalidwrites:
On 18 May 2008 at 10:46, Jens Thoms Toerring wrote:
>alternative...@gmail.com wrote:
>> int v = 1;
>> node *n = malloc(sizeof(node));
>> n->value = &v;
>Here you have a bad problem. What you store in the 'value' member
>is a pointer to a variable that vanishes the moment you return
>from this function.
You're right, but perhaps it will also be helpful to mention to the OP
that tracking down such bugs is very easy using the valgrind tool, which
will pick up invalid memory accesses like this. (This is just in case
the OP isn't a preternaturally talented programmer like all the clc
regulars, who as we know have no need for debugging tools besides their
eyes.)
If the OP is using Linux (or Windows too I think) then splint is also
quite good. I got the link from this group I think.

While splint indeed gives you some hint at what's going wrong
(alas in a way that probably will make it hard for the OP to
grasp) using valgrind seems to me like looking for your mis-
placed keys with a microscope. All it tells you is something
about an invalid read in the affiche() function, rather likely
just reinforcing the OP in the wrong belive that there would
be something wrong with this function and not helping at all
in finding the real reason for the problem. I would recommend
to use valgrind (or similar memory debuggers) only as a last
resort and instead to learn to avoid such mistakes since val-
grind can only detect the results of those mistakes, not the
mistakes themselves.
While I don't often agree with Mr. Twink, but I think that (assuming
the OP is using Linux, of which I can see absolutely no hint in his
post) using valgrind early and often is a good thing. Even on
programs that seem to work. I added it to our large regression suite
a while back at work and found a number of defects that way that had
not been otherwise noticed. They were of the class of things (e.g.
off by one errors causing invalid memory reads/writes) that can cause
difficult to diagnose at the customer site memory corruptions, but
often aren't detected in unit testing... I'm thus a big fan of using
valgrind (and in the past purify) at any stage of development...

I also agree with your point to some degree, that being able to find
these things by eye is a good thing. A competent code inspector
should be able to catch return of automatic memory (or putting it into
a struct that is returned).

-David
Jun 27 '08 #7
David Resnick <ln********@gmail.comwrote:
On May 18, 4:54 pm, j...@toerring.de (Jens Thoms Toerring) wrote:
While splint indeed gives you some hint at what's going wrong
(alas in a way that probably will make it hard for the OP to
grasp) using valgrind seems to me like looking for your mis-
placed keys with a microscope. All it tells you is something
about an invalid read in the affiche() function, rather likely
just reinforcing the OP in the wrong belive that there would
be something wrong with this function and not helping at all
in finding the real reason for the problem. I would recommend
to use valgrind (or similar memory debuggers) only as a last
resort and instead to learn to avoid such mistakes since val-
grind can only detect the results of those mistakes, not the
mistakes themselves.
While I don't often agree with Mr. Twink, but I think that (assuming
the OP is using Linux, of which I can see absolutely no hint in his
post) using valgrind early and often is a good thing. Even on
programs that seem to work. I added it to our large regression suite
a while back at work and found a number of defects that way that had
not been otherwise noticed. They were of the class of things (e.g.
off by one errors causing invalid memory reads/writes) that can cause
difficult to diagnose at the customer site memory corruptions, but
often aren't detected in unit testing... I'm thus a big fan of using
valgrind (and in the past purify) at any stage of development...
I also agree with your point to some degree, that being able to find
these things by eye is a good thing. A competent code inspector
should be able to catch return of automatic memory (or putting it into
a struct that is returned).
I hope I didn't give the impression that I would be somehow
opposed to using valgrind and similar programs. I use it my-
self for exactly the purpose you describe, i.e. finding de-
fects and, if I am lucky, getting some hints what kind of
problem I have to look for. But what it's not IMHO is an all-
purpose debugging tool in the sense "write some code, run it
through valgrind and if it doesn't complain everything is
fine, otherwise it tells me where to look". It isn't that
already because to find the mistake one made from what val-
grind outputs can be a rater lengthy process, often not much
simpler than getting from e.g. a segmentation fault to the
exact place where the logical error in the program is. And
it isn't such an all-purpose debugging tool also since it
can only collect data from the parts of a program that have
actually been executed in the test run - running through each
and every possible path in a program can be nearly impossible.

I find it rather problematic to recommend valgrind to a relative
beginner in C programming. To be able to get something out of
the defects valgrind flags one needs to have at least some aware-
ness of the errors one can make. And I doubt very much that
someone who can't debug a <=50 lines program by eye has any
realistic chance of making head or tail of the output of val-
grind. The OP's program output clearly showed that there was a
severe problem and the only information valgrind in this case
adds is that there is an invalid read, but at a place that's
not the one where the principal problem is. Since I have a bit
of experience with C programming and (much too much:-) with
debugging all I would conclude from it is that I made a mistake
somewhere in the program, using already deallocated memory, ha-
ving passed back a pointer to a non-static, local variable etc.
And I know that the mistake can be at a completely different
place from the one where valgrind found the defect and thus would
not concentrate my attention unnecessarily to just this place. On
the other hand, someone relatively new to programming in C will
rather likely have problems understanding what "invalid read"
actually signifies and assume that the problem is somewhere near
to where valgrind found the defect, spending lots of time looking
for bugs that don't exist. That's at least the conclusion I draw
from my own learning of how to debug and observing what other
people struggle with.
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
Jun 27 '08 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

49
by: Steven Bethard | last post by:
I promised I'd put together a PEP for a 'generic object' data type for Python 2.5 that allows one to replace __getitem__ style access with dotted-attribute style access (without declaring another...
18
by: Steven Bethard | last post by:
In the "empty classes as c structs?" thread, we've been talking in some detail about my proposed "generic objects" PEP. Based on a number of suggestions, I'm thinking more and more that instead of...
4
by: Ben | last post by:
Hi, I was writing a expression template for string concatenation latetly. When writing it, I started to feel curious that why there's not any generic et lib that can save me from wring each...
0
by: Bonj | last post by:
hello this is a purely algorithmical question but if i have posted to an irrelevant group, apologies. can anyone point me at some good tutorials or info about the steps involved in creating a...
4
by: Mitchel Haas | last post by:
Hello, Feeling a need for a generic tree container to supplement the available containers in the STL, I've created a generic tree container library (TCL). The library usage is very much like...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.