Typecasting Pointers on a 64 bit System

I

Ian Collins

Why do people keep suggesting this?

If OP had, this thread would never have been born.
Pass-by-reference and threads aren't
known to play well. IMHO the OP had sensible intuition to pass the
descriptor by value. It may not be pretty in C, but neither is threaded
programming.

As long as the address is still valid when a thread dereferences it,
what's the problem?
 
J

James Kuyper

On 11/15/11 08:10 AM, William Ahern wrote: ....

As long as the address is still valid when a thread dereferences it,
what's the problem?

The possibility that the address might NOT still be valid at the time of
use. This has already been pointed out, and is explicitly considered
(but somehow ignored as unimportant) in your own response.
A relevant response would give reasons justifying your treatment of that
possibility as unimportant.
 
K

Keith Thompson

christian.bau said:
Now an optimizing compiler could easily conclude that producing a data
pointer value that is not a null pointer or a pointer to an object or
past the last byte of an object is always undefined behavior, and on
MacOS X 64 bit and probably on other 64 bit systems casting an int to
a pointer will _always_ invoke undefined behavior unless the int has a
value of 0, and that therefore the result is always a null pointer.
gcc tends to do that kind of optimizations and break "widely portable"
undefined behavior.

This:

void *ptr = 0;

is guaranteed to set ptr to a null pointer value, because the constant
0 is a null pointer constant. This:

int var = 0;
void *ptr = (int*)var;

is not (though it's likely to do so under most implementations).
 
I

Ian Collins

The possibility that the address might NOT still be valid at the time of
use. This has already been pointed out, and is explicitly considered
(but somehow ignored as unimportant) in your own response.

I had assumed a competent programmer would be aware of the issue. I had
further assumed a programmer writing threaded applications to be
competent. If either of those assumptions are untrue, the programmer's
foray into threaded programming will be brief and painful.
A relevant response would give reasons justifying your treatment of that
possibility as unimportant.

Where did I say it was unimportant? Do you expect me to qualify every
mention of passing an address?
 
J

jacob navia

Le 14/11/11 22:15, Ian Collins a écrit :
I had assumed a competent programmer would be aware of the issue. I had
further assumed a programmer writing threaded applications to be
competent. If either of those assumptions are untrue, the programmer's
foray into threaded programming will be brief and painful.

Well, it is not a matter of competence Ian, calm down. I think Mr Kuyper
wants to point out that a solution passing some pointer instead of a
value provokes further complexities that obviously *could* be handled
by a competent programmer but that complexify the interface of that
function...

If I understood him correctly that is.
 
I

Ian Collins

Le 14/11/11 22:15, Ian Collins a écrit :

Well, it is not a matter of competence Ian, calm down. I think Mr Kuyper
wants to point out that a solution passing some pointer instead of a
value provokes further complexities that obviously *could* be handled
by a competent programmer but that complexify the interface of that
function...

If I understood him correctly that is.

:)

I'm quite calm. I just had a strong urge to be pompous...

As an aside, the problem (a dangling pointer) tends not to happen with
pthreads because the default behaviour of pthread_create is to create a
joinable thread. So I'd also assumed there would be pthread_join
further on in the code.
 
J

James Kuyper

I had assumed a competent programmer would be aware of the issue. I had
further assumed a programmer writing threaded applications to be
competent. If either of those assumptions are untrue, the programmer's
foray into threaded programming will be brief and painful.

That second assumption seems unjustified to me, and I would say the same
about your assumption that the painful foray will be short. I've seen an
incompetent programmer spend several long painful months trying to deal
with problems caused by a much simpler misunderstanding (and I'm not
talking about Bill Cunningham). If the particular programmer I'm
thinking of had bothered spending 5 minutes asking me questions, that
waste could have been avoided, but I had no idea that he was wasting his
time that way. He was under orders to ask me questions if he ran into
trouble, but never did so - he never gave a coherent explanation of why
he didn't.

However, neither assumption seems to be relevant here. As long as this
is an issue that the programmer needs to be aware of, the need for such
awareness IS the problem that you're asking about.
Where did I say it was unimportant?

You asked "what's the problem?" in the same sentence where you conceded
both the existence and relevance of the problem you were asking about.
The simplest explanation I could come up with for such a seemingly
bizarre combination was that you considered the problem you mentioned to
be unimportant, and were challenging people to come up with a more
important one, with the expectation that they would not succeed. I'll
concede that there might be other reasons for writing a sentence with
that structure, but the variety of those other possible reasons is
great, and the probability that any particular one of them is justified
is small. It would improve my understanding of the point of your message
if you could explain your reason for posting such a question.
 
I

Ian Collins

You asked "what's the problem?" in the same sentence where you conceded
both the existence and relevance of the problem you were asking about.

In the same vein as "as long as you hold the knife by the handle, what's
the problem?".
The simplest explanation I could come up with for such a seemingly
bizarre combination was that you considered the problem you mentioned to
be unimportant, and were challenging people to come up with a more
important one, with the expectation that they would not succeed. I'll
concede that there might be other reasons for writing a sentence with
that structure, but the variety of those other possible reasons is
great, and the probability that any particular one of them is justified
is small. It would improve my understanding of the point of your message
if you could explain your reason for posting such a question.

Wow, I consider my pomposity well and truly trumped!
 
J

James Kuyper

In the same vein as "as long as you hold the knife by the handle, what's
the problem?".

I would interpret a question such as that as one which dismisses the
importance of having to hold the knife by the handle, because it's easy
to arrange to do so. I had assumed you were doing the same: implicitly
asserting that it's trivial to arrange that the address remains valid; I
was rather surprised when you vehemently denied that inference. I had
expected an explanation of why it is trivial.
 
B

Ben Pfaff

James Kuyper said:
I would interpret a question such as that as one which dismisses the
importance of having to hold the knife by the handle, because it's easy
to arrange to do so. I had assumed you were doing the same: implicitly
asserting that it's trivial to arrange that the address remains valid; I
was rather surprised when you vehemently denied that inference. I had
expected an explanation of why it is trivial.

Sure it's trivial. In the old thread, malloc(sizeof(int)), put
the file descriptor there and pass the malloc'd pointer. In the
new thread, dereference the pointer to get the file descriptor,
then free it.
 
I

Ian Collins

I would interpret a question such as that as one which dismisses the
importance of having to hold the knife by the handle, because it's easy
to arrange to do so. I had assumed you were doing the same: implicitly
asserting that it's trivial to arrange that the address remains valid; I
was rather surprised when you vehemently denied that inference. I had
expected an explanation of why it is trivial.

I think our opinions on what constitutes common sense differ somewhat.
I see not passing a pointer to something that has gone out of scope in
the same way as not holding a knife by the blade. In both cases, doing
the consequences of doing the wrong thing tend to deter a repeat.

Or maybe I've just been doing this stuff for way to long...
 
J

Joe Pfeiffer

Ian Collins said:
I had assumed a competent programmer would be aware of the issue. I
had further assumed a programmer writing threaded applications to be
competent. If either of those assumptions are untrue, the
programmer's foray into threaded programming will be brief and
painful.

Painful, anyway :)
 
S

Seebs

Probably; I think that the existence of "common sense" is a popular
delusion, based upon people projecting onto others their own
understanding of things. People suffering from that delusion often hold
those others to blame for the failure of that projection to match reality.

I tend towards this view, myself.

If nothing else, I do not consider it safe to assume that generic programmers
not previously verified to understand the issues have any awareness of the
issues of passing the address of "some object somewhere" into a thread
mechanism or the like.

Heck.

Consider:

struct foo *f = malloc(sizeof(*f));
free(f);
f->x = 1;

I do not consider it a reasonable assumption that an arbitrary person
with 3-5 years or more of experience programming C will see anything
wrong here. I've seen someone who had >10 years claimed experience and
got promoted to lead engineer for a project who insisted that this was
not only permissible but the only way to avoid memory leaks in C.

.... And yes, the project failed utterly and everyone involved lost their
jobs. Funny only because it was over a decade ago. :)

It is very easy for people who have finally been taught that it's not okay
to return the address of a local variable to conclude that it's fine to
pass the address of a local variable to a function you call. And you're
*calling* pthread_create(), see. So that's fine.

Worse yet if they have done a lot of work in a language with closures. :)

-s
 
J

James Kuyper

On 11/14/2011 05:29 PM, Ian Collins wrote:
....
I think our opinions on what constitutes common sense differ somewhat.

Probably; I think that the existence of "common sense" is a popular
delusion, based upon people projecting onto others their own
understanding of things. People suffering from that delusion often hold
those others to blame for the failure of that projection to match reality.
I see not passing a pointer to something that has gone out of scope in
the same way as not holding a knife by the blade. In both cases, doing
the consequences of doing the wrong thing tend to deter a repeat.

Or maybe I've just been doing this stuff for way to long...

Attempting to dereference a pointer to memory that has already been
deallocated is one of the most common nasty mistakes made by C
programmers. There are many other mistakes that are more common, but
most of them are easier to diagnose than that one. I'm no expert in
multi-threaded code, but it seems to me that the problem can only be
worse if the dynamically allocated memory is shared between threads.

Several participants on this thread suggested that this was a serious
problem, you've suggested that its trivial. I think that they may be
exaggerating the difficulty, while you may be doing the opposite; I was
hoping to provoke a more detailed discussion that would clarify the
discrepancy. Instead I seem to have only provoked a discussion about my
provocation.
 
I

Ian Collins

On 11/14/2011 05:29 PM, Ian Collins wrote:
....

Probably; I think that the existence of "common sense" is a popular
delusion, based upon people projecting onto others their own
understanding of things. People suffering from that delusion often hold
those others to blame for the failure of that projection to match reality.

You're probably right there!
Attempting to dereference a pointer to memory that has already been
deallocated is one of the most common nasty mistakes made by C
programmers. There are many other mistakes that are more common, but
most of them are easier to diagnose than that one. I'm no expert in
multi-threaded code, but it seems to me that the problem can only be
worse if the dynamically allocated memory is shared between threads.

Sharing dynamically allocation memory between threads isn't really any
mode dangerous than using it in single threaded applications. The same
care has to be taken in determining where the memory is released. It
goes without saying the problem largely evaporates in C++ with smart
pointers.
Several participants on this thread suggested that this was a serious
problem, you've suggested that its trivial. I think that they may be
exaggerating the difficulty, while you may be doing the opposite; I was
hoping to provoke a more detailed discussion that would clarify the
discrepancy. Instead I seem to have only provoked a discussion about my
provocation.

I didn't so much suggest it was trivial, only that is was no worse than
any other situation with pointers. If you understand threading that is!
 
P

Phil Carmody

James Kuyper said:
I would interpret a question such as that as one which dismisses the
importance of having to hold the knife by the handle, because it's easy
to arrange to do so. I had assumed you were doing the same: implicitly
asserting that it's trivial to arrange that the address remains valid;

By default, addresses remain valid unless you explicitly do something
that makes them invalid.

Phil
 
P

Phil Carmody

Seebs said:
Consider:

struct foo *f = malloc(sizeof(*f));
free(f);
f->x = 1;

I do not consider it a reasonable assumption that an arbitrary person
with 3-5 years or more of experience programming C will see anything
wrong here.

Astounding. And I say that as someone who's spent a long time in maintenance
fixing major ****-ups by people who just didn't get it. But not one of them
(even the "we've read /Design Patterns/, we don't have to care about O(n^2)
getting huge" crowd, and even the "shift by N bits by shifting by 1 bit N-1
times" dude) would have done *that*.

I hope you're exagerating. I guess I should get a nice warm feeling of
comfort that ${DAYJOB} really is about as great a bunch of coders as
you could ever hope to work with.

Phil
 
J

James Kuyper

By default, addresses remain valid unless you explicitly do something
that makes them invalid.

Off-hand I can think of three ways by which previously valid addresses
can be come invalid, and three of them are quite explicit: free(),
realloc(), and fclose().
However, the addresses of variables with automatic storage duration
become invalid as soon as execution of the block in which they are
defined ends; that seems pretty implicit to me. YMMV

I hope you're not suggesting that the fact that free(), realloc() and
fclose() can only occur explicitly somehow makes it trivial to ensure
that they have not yet been called for a given pointer? If that were the
case, garbage collection wouldn't be as popular an extension as it is.
Even in single-threaded code it takes a certain amount of discipline to
ensure that a pointer is not used after the memory it points to has been
free()d.

When possible, I try to make sure that pointers into dynamically
allocated memory are stored only in automatic objects whose lifetime
ends immediately after the call to free(), rendering it impossible for
such problems to occur. However, it's not always possible to impose such
restrictions. When I can't do that, I insert code setting the pointer to
NULL immediately after the free(). However, to be helpful, that requires
that I protect all problematic uses of such a pointer with tests to
determine whether it's null.

When the expressions p=malloc(), *p=3, x=*p, and free(p) occur in two or
more different threads executing asynchronously, it seems to me that it
would be all that much harder to ensure that they occur only in the
proper order. I'm not saying it's impossible - just that it's harder.
Though Ian has assured me that this is not the case, I don't quite see
how that could be.
 
J

James Kuyper

On 11/16/2011 06:53 AM, James Kuyper wrote:
....
Off-hand I can think of three ways by which previously valid addresses

Yes, I can count. However, when I decided to add realloc() to the list,
I forgot to update that to "four".
 

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

Forum statistics

Threads
474,083
Messages
2,570,591
Members
47,212
Latest member
RobynWiley

Latest Threads

Top