469,625 Members | 1,097 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,625 developers. It's quick & easy.

Why pA->foo() works in this code?

Hi

why this code works?

#include <iostream>

class A {
public:
void foo() {std::cout << "hi" << std::endl; };
};

void MakeA(A *pA) { pA = new A; }

int main() {
A* pA = NULL;
Make(pA);
pA->foo();
delete pA;

return 0;
}

And... why ((A*)NULL)->foo() works too?

Thanks in advance.
Jan 15 '08 #1
8 1437
Luis Angel Fernandez Fernandez wrote:
why this code works?

#include <iostream>

class A {
public:
void foo() {std::cout << "hi" << std::endl; };
};

void MakeA(A *pA) { pA = new A; }

int main() {
A* pA = NULL;
Make(pA);
pA->foo();
delete pA;

return 0;
}

And... why ((A*)NULL)->foo() works too?
The code has undefined behaviour (UB). One of the results of UB
is the appearance of being "working". Read up on UB and don't
write code like that.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jan 15 '08 #2
On Jan 15, 10:59 am, Luis Angel Fernandez Fernandez
<laff...@gmail.comwrote:
Hi

why this code works?
why shouldn't it?
>
#include <iostream>

class A {
public:
void foo() {std::cout << "hi" << std::endl; };
extra semicolon above
>
};

void MakeA(A *pA) { pA = new A; }

int main() {
A* pA = NULL;
Make(pA);
pA->foo();
delete pA;

return 0;

}

And... why ((A*)NULL)->foo() works too?
jump off a bridge: does that work too?
Modify type A by adding a member, then modify or access that member
with foo().
Do you still think you can jump off the bridge?
>
Thanks in advance.
Jan 15 '08 #3
On 15 Jan, 15:59, Luis Angel Fernandez Fernandez <laff...@gmail.com>
wrote:
* Hi
* why this code works?

class A {
* public:
* * void foo() {std::cout << "hi" << std::endl; };
};

void MakeA(A *pA) { pA = new A; }
This just sets pA and then forgets it value: you mean
void MakeA(A*& pa) { pA = new A; }
int main() {
* A* pA = NULL;
* Make(pA);
* pA->foo();
* delete pA;

* return 0;

}

* And... why ((A*)NULL)->foo() works too?

* Thanks in advance.
This came up recently, see:
http://groups.google.co.uk/group/com...427ed638?hl=en
Jan 15 '08 #4
El Tue, 15 Jan 2008 08:15:40 -0800, tragomaskhalos escribió:

Hi, again.

Thank you all for your anwsers.
>void MakeA(A *pA) { pA = new A; }

This just sets pA and then forgets it value: you mean void MakeA(A*& pa)
{ pA = new A; }
That's what we thought, but when we saw it working (or doing something
it seemed right) we were surprised.

>Â* And... why ((A*)NULL)->foo() works too?

This came up recently, see:
http://groups.google.co.uk/group/com...thread/thread/
a807522e71a60c8e/f4afa72f427ed638?hl=en
Thank you. I was searching something about that, but I couldn't find
anything.

Bye.

--
Ubuntu 7.10 (gutsy) (kernel 2.6.22-14-generic i686) GNOME 2.20.1
Intel(R) Core(TM)2 Quad CPU (2260.245 MHz) up 33 min, 2 users
HT: ZanzabornÃ*n (1457021) X.1762 # http://muxin.no-ip.org/
SK: C.D. Arrancatapinos (18088) IV.57 # Jabber: la*****@gmail.com
Jan 15 '08 #5
Salt_Peter <pj*****@yahoo.comwrites:
On Jan 15, 10:59 am, Luis Angel Fernandez Fernandez
<laff...@gmail.comwrote:
[...]
> And... why ((A*)NULL)->foo() works too?

jump off a bridge: does that work too?
There are small bridges, and there are high bridges ;-)
Modify type A by adding a member, then modify or access that member
with foo().
Do you still think you can jump off the bridge?
--
__Pascal Bourguignon__ http://www.informatimago.com/
Until real software engineering is developed, the next best practice
is to develop with a dynamic system that has extreme late binding in
all aspects. The first system to really do this in an important way
is Lisp. -- Alan Kay
Jan 15 '08 #6
On Jan 15, 1:40 pm, "Luis Angel Fdez. Fdez." <laff...@gmail.com>
wrote:
El Tue, 15 Jan 2008 08:15:40 -0800, tragomaskhalos escribió:

Hi, again.

Thank you all for your anwsers.
void MakeA(A *pA) { pA = new A; }
This just sets pA and then forgets it value: you mean void MakeA(A*& pa)
{ pA = new A; }

That's what we thought, but when we saw it working (or doing something
it seemed right) we were surprised.
It doesn't forget its value, the pointer is passed by value. In other
words, the pointer pA in main() is indeed pointing to a valid new
allocation upon function return. Of course, there is a syntax error in
main():
Make(pA);
should be
MakeA(pA);

as far as the following is concerned, ask yourself: is a constructor
of any kind invoked? no, hence undefined behaviour.
>
And... why ((A*)NULL)->foo() works too?
This came up recently, see:
http://groups.google.co.uk/group/com...thread/thread/
a807522e71a60c8e/f4afa72f427ed638?hl=en

Thank you. I was searching something about that, but I couldn't find
anything.

Bye.

--
Ubuntu 7.10 (gutsy) (kernel 2.6.22-14-generic i686) GNOME 2.20.1
Intel(R) Core(TM)2 Quad CPU (2260.245 MHz) up 33 min, 2 users
HT: Zanzabornín (1457021) X.1762 #http://muxin.no-ip.org/
SK: C.D. Arrancatapinos (18088) IV.57 # Jabber: laff...@gmail.com
Jan 15 '08 #7
Luis Angel Fernandez Fernandez wrote:
Hi

why this code works?

#include <iostream>

class A {
public:
void foo() {std::cout << "hi" << std::endl; };
};

void MakeA(A *pA) { pA = new A; }
From your question I think you understand that pA in main is not being
changed, that the pA in this function is a temporary and that after this
function is closed there is no way to delete the newed A.
int main() {
A* pA = NULL;
Make(pA);
pA->foo();
pA points to NULL still. Now, why does pA->foo(); work? It is undefined
behavior. However. Most compilers (if not all?) would actually convert
this to a call like:
foo( pA );

There is only one copy of the function A::foo() even if you have 100
instances of A. The hidden this pointer points to the instance of the
class, in this case NULL. Your function
void foo() {std::cout << "hi" << std::endl; };
does not attempt to dereference the this pointer (it does not try to access
any variables of the class) so for this undefined behavior you are getting
output. If you want to see different behavior for the exact same call, try
changing your class to:

class A {
public:
void foo() {std::cout << "hi" << i << std::endl; };
private:
int i;
};

and running the program and you should see a memory access violation reading
some location. That's because now the function is attempting to dereference
the this pointer, << i << becoming something like << this->i << which is
NULL plus some offset.

You can not count on undefined behavior, it is undefined. Sometimes you can
explain it however, but that doesn't mean you should count on it to always
work that way on different compilers or even the same compiler.
delete pA;

return 0;
}

And... why ((A*)NULL)->foo() works too?
Same as above. It becomes in the compiler foo( NULL );
Thanks in advance.
--
Jim Langston
ta*******@rocketmail.com
Jan 16 '08 #8
On Jan 15, 4:36 pm, Pascal Bourguignon <p...@informatimago.comwrote:
Salt_Peter <pj_h...@yahoo.comwrites:
On Jan 15, 10:59 am, Luis Angel Fernandez Fernandez
<laff...@gmail.comwrote:
[...]
And... why ((A*)NULL)->foo() works too?
jump off a bridge: does that work too?

There are small bridges, and there are high bridges ;-)
feel free to test the difference.
>
Modify type A by adding a member, then modify or access that member
with foo().
Do you still think you can jump off the bridge?

--
__Pascal Bourguignon__ http://www.informatimago.com/
Until real software engineering is developed, the next best practice
is to develop with a dynamic system that has extreme late binding in
all aspects. The first system to really do this in an important way
is Lisp. -- Alan Kay
Jan 16 '08 #9

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

6 posts views Thread by Abhijeet | last post: by
6 posts views Thread by Bryan | last post: by
16 posts views Thread by Colin JN Breame | last post: by
10 posts views Thread by Math | last post: by
8 posts views Thread by Martin Jørgensen | last post: by
5 posts views Thread by =?Utf-8?B?bXBhaW5l?= | last post: by
reply views Thread by gheharukoh7 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.