435,395 Members | 2,513 Online
Need help? Post your question and get tips & solutions from a community of 435,395 IT Pros & Developers. It's quick & easy.

# Undefined behaviour question

 P: n/a We all know that this: void *p; if (p=malloc(1)) { free(p); p; } causes undefined behaviour if malloc() succeeds. But what about this? void *p; if (p=malloc(1)) { free(p); &p; } I *think* this is perfectly safe and defined behaviour but as I have not read the standard I am not sure. -- /-- Joona Palaste (pa*****@cc.helsinki.fi) ------------- Finland --------\ \-- http://www.helsinki.fi/~palaste --------------------- rules! --------/ "O pointy birds, O pointy-pointy. Anoint my head, anointy-nointy." - Dr. Michael Hfuhruhurr Nov 14 '05 #1
8 Replies

 P: n/a Joona I Palaste wrote: We all know that this: void *p = malloc(1); if (NULL != p) { free(p); p; } causes undefined behavior if malloc() succeeds. But what about this? void *p = malloc(1); if (NULL != p) { free(p); &p; } I *think* this is perfectly safe and defined behavior but, as I have not read the standard, I am not sure. It is safe. Pointer p no longer points to a valid object after free(p) but p is still a valid pointer object so a pointer to p is a valid pointer object as well. Nov 14 '05 #2

 P: n/a In article , Joona I Palaste wrote: We all know that this: void *p; if (p=malloc(1)) { free(p); p; } causes undefined behaviour if malloc() succeeds. But what about this? void *p; if (p=malloc(1)) { free(p); &p; } I *think* this is perfectly safe and defined behaviour but as I have not read the standard I am not sure. Of course it is perfectly safe. All you do is taking the address of an existing object. The fact that the object contains nonsense doesn't cause any problem when you take its address. You might as well ask whether void *p; if (p = malloc (1)) { free (p); p = NULL; } causes problems. After all, you are assigning NULL to a variable containing an undefined value. Nov 14 '05 #3

 P: n/a Joona I Palaste wrote: We all know that this: void *p; if (p=malloc(1)) { free(p); p; } causes undefined behaviour if malloc() succeeds. But what about this? void *p; if (p=malloc(1)) { free(p); &p; } I *think* this is perfectly safe and defined behaviour but as I have not read the standard I am not sure. int i; int *p; p = &i; is that safe? does that answer your question? :-) -nrk. -- Remove devnull for email Nov 14 '05 #4

 P: n/a > We all know that this: void *p; if (p=malloc(1)) { free(p); p; } causes undefined behaviour if malloc() succeeds. Call me Mr. Deer-in-Headlights, but I'd always been taught that p; is a no-op. Furthermore, how about: if (p=malloc(1)) { int x = (int)p; free(p); x; } Casting a pointer to an int is implementation-defined (but not undefined), isn't it? There does not seem to be much difference between the above, and if (p=malloc(1)) { free(p); int x = (int)p; x; } My rationale: the reason it's undefined to use a pointer value (without dereferencing) is for systems where loading such a value to a memory access register causes an exception. However, if we are just converting to int, that register would not have to be used. Since the int cast is implementation-defined, the implementation could always do this without doing anything undefined. Nov 14 '05 #5

 P: n/a ol*****@inspire.net.nz (Old Wolf) writes: We all know that this: void *p; if (p=malloc(1)) { free(p); p; } causes undefined behaviour if malloc() succeeds. Call me Mr. Deer-in-Headlights, but I'd always been taught that p; is a no-op. It's not a no-op from the viewpoint of the standard. Rather, it calculates the value of variable `p'. Because the value of variable `p' is indeterminate (see C99 6.2.4#2) and thus may be a trap representation (see C99 3.17.2), that expression invokes undefined behavior. Furthermore, how about: if (p=malloc(1)) { int x = (int)p; free(p); x; } No pointer is involved, so if the conversion `(int) p' produced a value that is not a trap representation, it is still not a trap representation after the free(). Casting a pointer to an int is implementation-defined (but not undefined), isn't it? Not necessarily, see C99 6.3.2.3#6: If the result cannot be represented in the integer type, the behavior is undefined. There does not seem to be much difference between the above, and if (p=malloc(1)) { free(p); int x = (int)p; x; } That's undefined too, because the value of `p' is still being accessed. You could access the bytes in `p' through a character pointer if you like, though. My rationale: the reason it's undefined to use a pointer value (without dereferencing) is for systems where loading such a value to a memory access register causes an exception. That's a reasonable reason. However, if we are just converting to int, that register would not have to be used. But it's not required not to be used. Behavior is still undefined. Since the int cast is implementation-defined, the implementation could always do this without doing anything undefined. -- "Welcome to the wonderful world of undefined behavior, where the demons are nasal and the DeathStation users are nervous." --Daniel Fox Nov 14 '05 #6

 P: n/a Old Wolf wrote: We all know that this: void *p; if (p=malloc(1)) { free(p); p; } causes undefined behaviour if malloc() succeeds. Call me Mr. Deer-in-Headlights, but I'd always been taught that p; is a no-op. In abstract terms, p is evaluated, and then that value is discarded. Whilst any compiler /may/ optimise it out, it isn't /required/ to. Joona is right; the behaviour is undefined. Furthermore, how about: if (p=malloc(1)) { int x = (int)p; free(p); x; } Casting a pointer to an int is implementation-defined (but not undefined), isn't it? Yes. But in this case, all you're doing is giving x a valid (albeit implementation-defined) value. It /looks/ very similar to the first case, but in fact it isn't. There does not seem to be much difference between the above, and if (p=malloc(1)) { free(p); int x = (int)p; x; } Oh, there's a world of difference. This one (quite apart from not even compiling on C89) exhibits undefined behaviour in line 3, because of the evaluation of p. My rationale: the reason it's undefined to use a pointer value (without dereferencing) is for systems where loading such a value to a memory access register causes an exception. However, if we are just converting to int, that register would not have to be used. I can find no such guarantee in the Standard. Since the int cast is implementation-defined, the implementation could always do this without doing anything undefined. A cast is a process, taking a value as input. In getting the value for input to the casting process, you invoke undefined behaviour, so the cast is way too late. -- Richard Heathfield : bi****@eton.powernet.co.uk "Usenet is a strange place." - Dennis M Ritchie, 29 July 1999. C FAQ: http://www.eskimo.com/~scs/C-faq/top.html K&R answers, C books, etc: http://users.powernet.co.uk/eton Nov 14 '05 #7

 P: n/a Joona I Palaste wrote: We all know that this: void *p; if (p=malloc(1)) { free(p); p; } causes undefined behaviour if malloc() succeeds. Correct. But what about this? void *p; if (p=malloc(1)) { free(p); &p; } I *think* this is perfectly safe and defined behaviour but as I have not read the standard I am not sure. It is. You should. If you did, then you would be. Probably. -- Richard Heathfield : bi****@eton.powernet.co.uk "Usenet is a strange place." - Dennis M Ritchie, 29 July 1999. C FAQ: http://www.eskimo.com/~scs/C-faq/top.html K&R answers, C books, etc: http://users.powernet.co.uk/eton Nov 14 '05 #8

 P: n/a On 16 Dec 2003, Joona I Palaste wrote: causes undefined behaviour if malloc() succeeds. But what about this? void *p; if (p=malloc(1)) { free(p); &p; } I *think* this is perfectly safe and defined behaviour but as I have not read the standard I am not sure. Obviously: void reincarnate(void **p) { *p=malloc(1); } void test(void) { void *p; if (p=malloc(1)) { free(p); reincarnate(&p) } } Nov 14 '05 #9

### This discussion thread is closed

Replies have been disabled for this discussion.