Interesting pointer problem (g++ v 3.1.1-24)

O

Olaf Martens

Greetings!

Please consider the following piece of program code (note that I have stripped
quite a lot of code here):

int foo(void)
{
unsigned short l_valbuf; // address of this goes to another function
Objtype *l_item; // I want to get this one's data!

..
..
..

l_item->QueryData(&l_valbuf,BITMASK);

}

l_valbuf is to act as a buffer for a two-byte data entity to be read out from
an object refrenced by l_item.

Now, when I attempt to read out a piece of data (as defined by BITMASK) and
have it put into the local variable l_valbuf I get absolute nonsense (although
the address QueryData() receives is correct - I already have verified this).
But when I make l_valbuf global, everything works just fine. *boggle*
Anyone around who has experienced this or a similar problem?
Any ideas how to make this thing work properly with local variables? Or is
this some sort of subtle bug within g++?
I'm using GNU C++ version 3.1.1-24 for Linux (underlying kernel is 2.4.21-166)

Any help would be greatly appreciated.
 
E

E. Robert Tisdale

Olaf said:
Please consider the following piece of program code
(note that I have stripped quite a lot of code here):

To make it easier for us to figure out what you did wrong, I suppose.
int foo(void) {
unsigned short l_valbuf;
// address of this goes to another function
Objtype* l_item; // I want to get this one's data!

.
.
.

l_item->QueryData(&l_valbuf,BITMASK);

}

l_valbuf is to act as a buffer for a two-byte data entity
to be read out from an object refrenced by l_item.

Now, when I attempt to read out a piece of data (as defined by BITMASK)
and have it put into the local variable l_valbuf,

Can you show us exactly how you do this?
I get absolute nonsense (although the address QueryData()
receives is correct - I already have verified this).
But when I make l_valbuf global, everything works just fine. *boggle*
Anyone around who has experienced this or a similar problem?
Any ideas how to make this thing work properly with local variables?
Or is this some sort of subtle bug within g++?

No. You just screwed up.
I'm using GNU C++ version 3.1.1-24 for Linux
(underlying kernel is 2.4.21-166)

Please show us the definition of QueryData.
 
M

Mike Wahler

Olaf Martens said:
Greetings!

Please consider the following piece of program code (note that I have stripped
quite a lot of code here):

int foo(void)
{
unsigned short l_valbuf; // address of this goes to another function
Objtype *l_item; // I want to get this one's data!

.
.
.

l_item->QueryData(&l_valbuf,BITMASK);

}

l_valbuf is to act as a buffer for a two-byte data entity to be read out from
an object refrenced by l_item.

Now, when I attempt to read out a piece of data (as defined by BITMASK) and
have it put into the local variable l_valbuf I get absolute nonsense (although
the address QueryData() receives is correct - I already have verified this).
But when I make l_valbuf global, everything works just fine. *boggle*
Anyone around who has experienced this or a similar problem?
Any ideas how to make this thing work properly with local variables? Or is
this some sort of subtle bug within g++?
I'm using GNU C++ version 3.1.1-24 for Linux (underlying kernel is
2.4.21-166)

The only 'bug' I see is in your understanding of how automatic objects
work. In your above function, the objects 'l_valbuf' and 'l_item' are
*destroyed*, *cease to exist*, when the function returns. So if you
take the address of an automatic object, and then try to use that
address after the object has been destroyed, you get what the language
calls 'undefined behavior', which might be manifest as a crash if you're
lucky, or 'seem to work' if you're not.

You can extend the lifetime of an object of function scope by defining
it as 'static'. This makes its lifetime that of the entire program.

int foo(void)
{
static unsigned short l_valbuf;
/* etc */
}

-Mike
 
J

Jeff Schwab

Olaf said:
Greetings!

Please consider the following piece of program code (note that I have
stripped quite a lot of code here):

int foo(void)
{
unsigned short l_valbuf; // address of this goes to another function
Objtype *l_item; // I want to get this one's data!

.
.
.

l_item->QueryData(&l_valbuf,BITMASK);

}

l_valbuf is to act as a buffer for a two-byte data entity to be read out
from an object refrenced by l_item.

Now, when I attempt to read out a piece of data (as defined by BITMASK)
and have it put into the local variable l_valbuf I get absolute nonsense
(although the address QueryData() receives is correct - I already have
verified this). But when I make l_valbuf global, everything works just
fine. *boggle*
Anyone around who has experienced this or a similar problem?
Any ideas how to make this thing work properly with local variables? Or
is this some sort of subtle bug within g++?
I'm using GNU C++ version 3.1.1-24 for Linux (underlying kernel is
2.4.21-166)

Any help would be greatly appreciated.


It's hard to tell what's going wrong. It would be helpful if you posted
a minimal, correct piece of code to show the problem; that is, one with
complete (but short) function and type definitions.

Here's something to start with; see whether this produces the error
you're seeing in your larger program. The value printed should be 4.

struct S
{
void set_my_local_int( int* p, int i ) { *p = i; }
};

#include <iostream>

int main( )
{
int i = 0;
S s;

s.set_my_local_int( &i, 4 );

std::cout << i << '\n';
}
 
O

Olaf Martens

Jeff said:
Olaf Martens wrote:
[snip]


It's hard to tell what's going wrong. It would be helpful if you posted
a minimal, correct piece of code to show the problem; that is, one with
complete (but short) function and type definitions.

Thanks for the help, but by coincidence I managed to fix the problem: When I
initialize the variable l_valbuf with some arbitrary value (static and the
likes is not necessary in this case) the call of
l_item->QueryData(&l_valbuf,BITMASK); works like a charm. I don't know what
was going on before the modification, but I already noticed during a debug
session that g++ is packing multiple variables in one spot (providing they are
used strictly in sequence, and no variable is ever accessed again once the
next variable comes to use), and so some other operation must have trashed the
(uninitialized) var after the function call returned.
 
P

Paul

Olaf said:
Jeff said:
Olaf Martens wrote:
[snip]
Thanks for the help, but by coincidence I managed to fix the problem:
When I initialize the variable l_valbuf with some arbitrary value
(static and the likes is not necessary in this case) the call of
l_item->QueryData(&l_valbuf,BITMASK); works like a charm.

The issue is that you have a local variable, and passing the address of
the local variable to a function called QueryValue. QueryValue is
supposed to change the value of the local variable. When you return
from QueryValue, you expect a certain value for l_valbug.

OK, so are you testing l_valbuf *immediately* after the call from
QueryData? If l_valbuf is being checked there, then either

1) QueryData is buggy, or

2) there is something about QueryData that relies on l_valbuf being set
beforehand, or

3) you are just not using QueryData properly (i.e. it needs to be called
after other functions have been called).

Those are the *only* possibilities that I can think of *if* you are
checking l_valbuf *immediately* after the call to QueryValue. If you're
doing a whole bunch of other stuff after the call to QueryValue, and
then check l_valbuf *within the foo function*, then your original
question cannot be answered until we see what you did in the time you
called QueryValue, and when you actually checked the l_valbuf value.

If you are leaving the foo() function, and for some reason expecting
l_valbuf to retain your data, that isn't going to work for the obvious
reason that local variables will be destroyed on function exit.

In any event, never blame the compiler first for something very simple
as passing an address and not expecting the results you desire. 99.9%
percent of the time for "bugs" such as this, it is the fault of the
coder not understanding some aspect of C++ and pointers or the program
is doing something illegal. Before even hinting of a compiler bug, just
think: if the compiler (g++ in this case) had such a problem with a
simple concept of pointer passing, literally thousands of other
programmers would have encountered it and would have reported it (and
hopefully it would have been fixed). The g++ compiler is mature enough
to not have such an obvious bug such as passing a pointer to a local and
have things screw up.

Paul
 
P

Paul

Paul wrote:

Of course, where I stated QueryValue in my previous post, it should be
QueryData.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,160
Messages
2,570,889
Members
47,420
Latest member
ZitaVos505

Latest Threads

Top