473,899 Members | 2,942 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

assigning a pointer the address of local variable

Suppose I have a code like this,

#include <stdio.h>

int *p;
void foo(int);

int main(void){
foo(3);
printf("%p %d\n",p,*p);
return 0;
}

void foo(int r){
int s=r+1;
p=&s;
}

In most of the compilers I use (GCC, MSVC++, lcc..) this program runs
allright printing an address and the correct value 4. But is it correct
to assign a global pointer the address of a local variable which does
not exist after the function has ended?

Aug 23 '06
25 9559
en******@yahoo. com wrote:
Harald van Dijk wrote:
Flash Gordon wrote:
en******@yahoo. com wrote:
Harald van Dijk wrote:
Keith Thompson wrote:
>jaysome <ja*****@spamco p.netwrites:
>>On Wed, 23 Aug 2006 06:32:54 GMT, Keith Thompson <ks***@mib.or g>
>>wrote:
>[...]
>>>No, it isn't. When s reaches the end of its lifetime (at the end of
>>>foo(), the value of p becomes indeterminate. Dereferencing p, or even
>>>looking at its value, invokes undefined behavior. (The latter isn't
>>>likely to cause any visible problems on most systems, but you should
>>>still avoid it.)
>>The word "looking" is vague. Does it mean that I can't do something
>>like this?
>>>
>>#include <stdio.h>
>>>
>>static int* foo(void);
>>>
>>int main(void)
>>{
>> int *p;
>> p = foo();/* legal? */
>> printf("Pointer was %p\n", (void*)p);/* legal? */
>> return 0;
>>}
>>>
>>static int* foo(void)
>>{
>> int i;
>> return &i;
>>}
>Any reference to the value of p after foo() returns invokes undefined
>behavior. For that matter, I think assigning the result of foo()to p
>in the first place invokes UB.
A question: what about just "foo();" (without an assignment)? Is the value
allowed to be read before discarding it?

No, I would say it isn't; otherwise the implementation would
be doing something not done by the abstract machine, violating
the as-if rule. To say it another way, the implementation is
allowed to read the value, but must behave as if it doesn't.
>
I agree with ena8t8si and would add in support that in C89 at least if
you fell off the end of the function without returning a value the
program would still be strictly conforming *if* you did not use the
value. So if "foo();" is fine if nothing is returned it must surely
still be fine if a value you are not allowed to use is returned.
Thanks. Now for my followup question: how does this affect an
expression statement consisting of a single volatile variable? Is a
read allowed?

Not just allowed, but required.
So the result of an expression-statement must not be read if it is a
function call, and must be read if it is a variable (and all exceptions
are results of the as-if rule)? Where does the standard make this
distinction?

Aug 25 '06 #21
[Originally, we had code equivalent to the following:

int *foo(void) { int i; return &i; }
int main(void) { foo(); return 0; }

I myself do not know whether this code is well-defined. We can
say for sure that "i" does exist at the point of the "return"
statement that takes its address, and no longer exists by the
time foo() has returned to main(), so the "value" returned by
the function has undefined behavior if it is used -- but it is
not "used".]
>>Harald van Dijk wrote:
>>>Thanks. Now for my followup question: how does this affect an
expression statement consisting of a single volatile variable? Is a
read allowed?
>en******@yahoo .com wrote:
>Not just allowed, but required.
In article <11************ **********@p79g 2000cwp.googleg roups.com>,
Harald van Dijk <tr*****@gmail. comwrote:
>So the result of an expression-statement must not be read if it is a
function call, and must be read if it is a variable (and all exceptions
are results of the as-if rule)? Where does the standard make this
distinction?
This is an interesting point. Here is Program P:

extern volatile int hardware_reg;

int main(void) {
volatile int *p = &hardware_re g;

*p; /* or, equivalently, "hardware_r eg;" (without quotes) */
return 0;
}

When run (after compiling with special Linker Magic to make the
external variable "hardware_r eg" correspond to a hardware register
on the system), this program clears the register -- it is one of
those "self-clearing upon read" registers -- and is thus useful
after some particular kinds of errors. (Perhaps the error it clears
has to do with the audio subsystem, so it makes the sound work on
the machine again.)

Now we modify Program P a bit, giving Program Q:

extern volatile int hardware_reg;
volatile int *f(void) { return &hardware_re g; }
int main(void) { *f(); return 0; }

This obviously does the same as Program P. But note that we used
the unary "*" operator in main(). If we had done that with the
original program, now modified to become Program R:

int *foo(void) { int i; return &i; }
int main(void) { *foo(); return 0; }

we would definitely (I believe) have undefined behavior. So now
we might write Program S:

volatile int *foo(void) { int i; return &i; }
int main(void) { foo(); return 0; }

The key seems, in this case, to be the unary "*" operator. It
is OK to skip "reading" the value returned by some function,
even if it is a "pointer to volatile", as long as we do not
actually follow the pointer.

If a function could return a volatile-qualified type (and it cannot),
and if the volatile-qualified type were a C++-like reference (which
C lacks), we could rewrite one of the above to produce Program T:

volatile int &f(void) { return hardware_reg; }
int main(void) { f(); return 0; }

In this case the actual read of the hardware register would occur
(logically at least) in main(), rather than in f(), giving rise to
the potential conflict that Harald is asking about. Fortunately,
we cannot express the problem in C in the first place. :-)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Aug 25 '06 #22

Chris Torek wrote:
[Originally, we had code equivalent to the following:

int *foo(void) { int i; return &i; }
int main(void) { foo(); return 0; }

I myself do not know whether this code is well-defined. We can
say for sure that "i" does exist at the point of the "return"
statement that takes its address, and no longer exists by the
time foo() has returned to main(), so the "value" returned by
the function has undefined behavior if it is used -- but it is
not "used".]
Here's why it's defined:

The value &i is valid when the expression is evaluated
before doing the return.

What the return does with the value is defined in
6.8.6.4 paragraph 3 - "the value is returned to the
caller".

An indeterminate value isn't illegal in and of itself;
it's only certain uses of indeterminate values that
cause undefined behavior:

6.2.6.1#5 - being read out of an object
6.2.6.1#5 - being stored into an object (perhaps indirectly)
6.2.6.2#4 - logical operators that would produce one
6.5.3.2#4 - operand of * operator

What a return does isn't any of these things; in
particular, a value of an expression isn't an object,
since it doesn't have an address. The implicit
conversion to (void) then discards the value, which
also doesn't violate any of the UB's.

Since the semantics are defined, and don't transgress any
provisions that would make them undefined, the result is defined.

Aug 26 '06 #23

Harald van Dijk wrote:
en******@yahoo. com wrote:
Harald van Dijk wrote:
Flash Gordon wrote:
en******@yahoo. com wrote:
Harald van Dijk wrote:
>Keith Thompson wrote:
>>jaysome <ja*****@spamco p.netwrites:
>>>On Wed, 23 Aug 2006 06:32:54 GMT, Keith Thompson <ks***@mib.or g>
>>>wrote:
>>[...]
>>>>No, it isn't. When s reaches the end of its lifetime (at theend of
>>>>foo(), the value of p becomes indeterminate. Dereferencing p, or even
>>>>looking at its value, invokes undefined behavior. (The latter isn't
>>>>likely to cause any visible problems on most systems, but youshould
>>>>still avoid it.)
>>>The word "looking" is vague. Does it mean that I can't do something
>>>like this?
>>>>
>>>#include <stdio.h>
>>>>
>>>static int* foo(void);
>>>>
>>>int main(void)
>>>{
>>> int *p;
>>> p = foo();/* legal? */
>>> printf("Pointer was %p\n", (void*)p);/* legal? */
>>> return 0;
>>>}
>>>>
>>>static int* foo(void)
>>>{
>>> int i;
>>> return &i;
>>>}
>>Any reference to the value of p after foo() returns invokes undefined
>>behavior. For that matter, I think assigning the result of foo() to p
>>in the first place invokes UB.
>A question: what about just "foo();" (without an assignment)? Isthe value
>allowed to be read before discarding it?
>
No, I would say it isn't; otherwise the implementation would
be doing something not done by the abstract machine, violating
the as-if rule. To say it another way, the implementation is
allowed to read the value, but must behave as if it doesn't.

I agree with ena8t8si and would add in support that in C89 at leastif
you fell off the end of the function without returning a value the
program would still be strictly conforming *if* you did not use the
value. So if "foo();" is fine if nothing is returned it must surely
still be fine if a value you are not allowed to use is returned.
>
Thanks. Now for my followup question: how does this affect an
expression statement consisting of a single volatile variable? Is a
read allowed?
Not just allowed, but required.

So the result of an expression-statement must not be read if it is a
function call, and must be read if it is a variable (and all exceptions
are results of the as-if rule)? Where does the standard make this
distinction?
Chris Torek gave already a good answer to this, but let
me see if I can add to it.

My earlier answer was misleading, because "read" was being
used in two different senses. In both cases:

foo();
volatile_variab le;

a value is produced, and in both cases a value is discarded.
The difference is, in the case of foo(), producing the
value is ok because the value is valid at the time it's
produced, but in the case of volatile_variab le, the value
in the variable is already invalid when the variable is
accessed.

To say that another way, in neither case is the value of
the expression "read", but in the variable case an object
with an invalid value must be accessed, and it is this
access ("read" in the other sense) that causes the
undefined behavior. It isn't the value of the expression
that's read, but reading the variable to produce the
value of the expression, that causes the undefined
behavior; the value is subsequently discarded, but by
then it's too late, the UB has already happened.

Incidentally, the variable doesn't have to be volatile
to get undefined behavior.

See sections 6.3.2.1 #2, 6.2.6.1 #5 in the Standard.

Aug 26 '06 #24
en******@yahoo. com wrote:
Chris Torek wrote:
[Originally, we had code equivalent to the following:

int *foo(void) { int i; return &i; }
int main(void) { foo(); return 0; }

I myself do not know whether this code is well-defined. We can
say for sure that "i" does exist at the point of the "return"
statement that takes its address, and no longer exists by the
time foo() has returned to main(), so the "value" returned by
the function has undefined behavior if it is used -- but it is
not "used".]

Here's why it's defined:

The value &i is valid when the expression is evaluated
before doing the return.

What the return does with the value is defined in
6.8.6.4 paragraph 3 - "the value is returned to the
caller".

An indeterminate value isn't illegal in and of itself;
it's only certain uses of indeterminate values that
cause undefined behavior:

6.2.6.1#5 - being read out of an object
6.2.6.1#5 - being stored into an object (perhaps indirectly)
6.2.6.2#4 - logical operators that would produce one
6.5.3.2#4 - operand of * operator

What a return does isn't any of these things; in
particular, a value of an expression isn't an object,
since it doesn't have an address. The implicit
conversion to (void) then discards the value, which
also doesn't violate any of the UB's.

Since the semantics are defined, and don't transgress any
provisions that would make them undefined, the result is defined.
Thanks for the clear explanation, I think you're right. Now here's yet
another question:

int *foo(void) { int i; return &i; }
int *bar(void) { int i; return &i; }
int main(void) { return foo() == bar(); }

The invalid pointer values are not read by an lvalue expression, so
6.2.6.1p5 doesn't apply, and 6.5.9p6 says:

"Two pointers compare equal if and only if both are null pointers, both
are pointers to the same object (including a pointer to an object and a
subobject at its beginning) or function, both are pointers to one past
the last element of the same array object, or one is a pointer to one
past the end of one array object and the other is a pointer to the
start of a different array object that happens to immediately follow
the first array object in the address space.92)"

Neither value is a null pointer, neither value points to an object, and
neither value points to one past the last element of an array. Because
of the "if and only if", it seems that the above program is strictly
conforming and is guaranteed to return 0. That can't possibly be
intended, and at least three different compilers can all be convinced
to make the program return 1 in at least one mode which aims to conform
to C89 or C99.

Aug 26 '06 #25

Harald van Dijk wrote:
en******@yahoo. com wrote:
Chris Torek wrote:
[Originally, we had code equivalent to the following:
>
int *foo(void) { int i; return &i; }
int main(void) { foo(); return 0; }
>
I myself do not know whether this code is well-defined. We can
say for sure that "i" does exist at the point of the "return"
statement that takes its address, and no longer exists by the
time foo() has returned to main(), so the "value" returned by
the function has undefined behavior if it is used -- but it is
not "used".]
Here's why it's defined:

The value &i is valid when the expression is evaluated
before doing the return.

What the return does with the value is defined in
6.8.6.4 paragraph 3 - "the value is returned to the
caller".

An indeterminate value isn't illegal in and of itself;
it's only certain uses of indeterminate values that
cause undefined behavior:

6.2.6.1#5 - being read out of an object
6.2.6.1#5 - being stored into an object (perhaps indirectly)
6.2.6.2#4 - logical operators that would produce one
6.5.3.2#4 - operand of * operator

What a return does isn't any of these things; in
particular, a value of an expression isn't an object,
since it doesn't have an address. The implicit
conversion to (void) then discards the value, which
also doesn't violate any of the UB's.

Since the semantics are defined, and don't transgress any
provisions that would make them undefined, the result is defined.

Thanks for the clear explanation, I think you're right. Now here's yet
another question:

int *foo(void) { int i; return &i; }
int *bar(void) { int i; return &i; }
int main(void) { return foo() == bar(); }

The invalid pointer values are not read by an lvalue expression, so
6.2.6.1p5 doesn't apply, and 6.5.9p6 says:

"Two pointers compare equal if and only if both are null pointers, both
are pointers to the same object (including a pointer to an object and a
subobject at its beginning) or function, both are pointers to one past
the last element of the same array object, or one is a pointer to one
past the end of one array object and the other is a pointer to the
start of a different array object that happens to immediately follow
the first array object in the address space.92)"

Neither value is a null pointer, neither value points to an object, and
neither value points to one past the last element of an array. Because
of the "if and only if", it seems that the above program is strictly
conforming and is guaranteed to return 0. That can't possibly be
intended, and at least three different compilers can all be convinced
to make the program return 1 in at least one mode which aims to conform
to C89 or C99.
Yes, I think your analysis is right, and this
shows a weakness in the existing wording. You
might want to post the question in comp.std.c
in a new thread and see what other people think.
"If any pointer value is a trap representation
the behavior is undefined," or words to that
effect, should be added somewhere in 6.5.9,
and probably a few other places.

Aug 27 '06 #26

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

Similar topics

7
2663
by: NS Develop | last post by:
What's wrong with the following: void SomeClass::someMethod(void) { A *ptrA = NULL; ptrA = &A(); .... }
18
2963
by: Xiangliang Meng | last post by:
Hi. void setValue(int n) { int size = getValueLength(); int buffer_p; if (buffer_p) { ....
2
2699
by: Kench | last post by:
I was curious and playing with pointers and references to see what's different between them. Other than the obvious ones involving C++ syntax & things like references cannot be modified with addition & subtraction, pointers can be modified, both are similar. It stated me going what are the diferrence between a reference vairable and local variable ? Here are what I can think of 1. For a local variable constructor is called, not the case...
2
1370
by: Chris Stankevitz | last post by:
Hi, I have some weird behavior in a very large (500,000 line) program that I boiled down to a few lines: TCSensorMode::ProcessMeasurement() { InternalComplicatedFunction(1.0, 2.0); int a = abs(1); int b = abs(1);
4
11369
by: octavio | last post by:
Hello members of the comp.lang.c newsgroup. Please I need you help on the following one. Compiling the simple code I'm getting this error message. Why ? Please what's the correct type of the fb function ? Thank You. Octavio and.c:15: attention : type mismatch with previous implicit declaration and.c:11: attention : previous implicit declaration of `fb'
31
17722
by: leonm54 | last post by:
I remember that this is a bad practice, but can not find a definitive resource that states it is bad and why. Can anyone help?
14
16205
by: Spitfire | last post by:
Hi All, I've this weird question about pointers. I would like to know how to return the address of a local variable, safely!! Isn't that a unrecommended procedure? Doesn't it have possibilities that the variable could be deallocated from memory and the dereferencing of the returned pointer somewhere else could crash the program? If it's not safer to do such an operation, how do functions like strtok for example work??? --
3
2732
by: ali | last post by:
Hi, When I pass a pointer as an argument of a method, is it safe if I change the data pointed by the argument and return it upon completion ? For example: Object* someFunction(Object* ob) {
13
13210
by: hari | last post by:
Hi all, Is it legal to return a local variable from function. Regards Hari
0
9997
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, well explore What is ONU, What Is Router, ONU & Routers main usage, and What is the difference between ONU and Router. Lets take a closer look ! Part I. Meaning of...
0
9845
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 effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
1
10976
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 Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9671
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development projectplanning, coding, testing, and deploymentwithout human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
8043
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 presenter, Adolph Dupr who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
7204
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5891
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
2
4301
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
3320
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.