Pointers in c

S

Steffen Fiksdal

I have programmed a library which offers an API which takes both
'const char*' and 'char**' pointers as input parameters.

An example:

extern int apicall( int sessioncontext,
const char* input,
char** output );

This method will use the input data, do some processing, allocate memory
from heap and put the result of malloc() to *output. Then the memory is
filled with whatever....

If I am related to dr.ing. evil I might want to:

int res;
res=apicall(1,(const char*)12345,(char**)423B);


I would like to validate the inputB pointer
before reading from it (most probably creating a read segfault).
I have noticed that most people write: "You can't!".
Is it *absolutely* true. Is there no way I can look into segment registers
etc, to validate the range the pointer is in C?

The same question goes for a good write segfault candidate,
*output = malloc(10);, if output itself is garbage...

Best regards,
Steffen
 
I

infobahn

Steffen said:
I would like to validate the inputB pointer
before reading from it (most probably creating a read segfault).
I have noticed that most people write: "You can't!".

When you define a pointer, give it a valid value or assign NULL to it.
If its valid value ever becomes indeterminate, assign NULL to it
immediately (or give it another valid value). Ingrain this habit so
deeply into your programming that it becomes second nature.

When you have succeeded at this, all your pointers will either be
valid or NULL, so you can test them against NULL and know that, if
they are non-NULL, they are valid.
 
C

Chris Torek

I would like to validate [a] pointer
before reading from it (most probably creating a read segfault).
I have noticed that most people write: "You can't!".
Is it *absolutely* true. Is there no way I can look into segment registers
etc, to validate the range the pointer is in C?

Not in *standard* C.

Sometimes, not at all, but often, on many machines and operating
systems, there is some trick. The trick changes with OS and/or
machine.

You mentioned "segment registers", which suggests (but does not
require) that the machine in question is some variant of the x86.
This means you can write just a dozen or so different "verify
pointer" implementations: one for Linux, one for Windows N, one
for Windows N+2, one for BSD-based systems, one for OS/2, and so
on. Some of them may even share some code (in particular, all the
Unix-like/POSIX systems can probably use similar tricks).

(As an aside, the contents of the segment registers are unlikely
to help -- a "read segfault" suggests that you will be using a
paging system: despite the name "segmentation" fault, it is really
a page fault.)
 
K

Keith Thompson

Steffen Fiksdal said:
int res;
res=apicall(1,(const char*)12345,(char**)423B);

423B is a syntax error; do you mean 0x423B? A minor point.
I would like to validate the inputB pointer
before reading from it (most probably creating a read segfault).
I have noticed that most people write: "You can't!".
Is it *absolutely* true. Is there no way I can look into segment registers
etc, to validate the range the pointer is in C?

There is no way in portable C to validate a pointer, other than
comparing it to NULL (and even that can invoke undefined behavior if
the pointer value is indeterminate). Note that C has no concept of
segment registers. There might be system-specific ways to do it, but
of course they'll vary from system to system, and we can't go into
details here (and as far as I know most systems don't even have a
system-specific way to do this).

The workaround is to code carefully and avoid using invalid pointers
in the first place.
The same question goes for a good write segfault candidate,
*output = malloc(10);, if output itself is garbage...

Same answer.
 
M

Mark McIntyre

On Sun, 26 Dec 2004 20:20:15 +0100, in comp.lang.c , Steffen Fiksdal

(of validating that a pointer is ok to write to/read from)
before reading from it (most probably creating a read segfault).
I have noticed that most people write: "You can't!".
Is it *absolutely* true.

Its true as far as standard C is concerned. There's no way to check if
memory is valid because accessing invalid memory causes undefined behaviour
and your programme is entitled to behave implausibly from then on
Is there no way I can look into segment registers
etc, to validate the range the pointer is in C?

C has no concept of segment registers. You may find some platform-specific
extensions that do permit this sort of stuff but its not within the realms
of C.
The same question goes for a good write segfault candidate,
*output = malloc(10);, if output itself is garbage...

The langauge itself guarantees that output will be either a valit pointer,
or a null pointer. If might later on be invalidated by a fault in your
code, but thats not C's fault... :)
 
C

Chris Barts

Steffen said:
If I am related to dr.ing. evil I might want to:

int res;
res=apicall(1,(const char*)12345,(char**)423B);

Yes, that would be a valid, (probably) undetectable way to corrupt your
library and very likely crash the program that has linked into it.
I would like to validate the inputB pointer
before reading from it (most probably creating a read segfault).

You can't. At least, you probably can't. And if you can, you won't find
out how on this newsgroup.
I have noticed that most people write: "You can't!".

Why do you doubt them?
Is it *absolutely* true. Is there no way I can look into segment registers
etc, to validate the range the pointer is in C?

It might or might not be true on your system for your OS. It's probably
the case that you can't fully verify any pointer passed in from the
outside, beyond checking against NULL and whatever other system-specific
values you know are invalid in your specific case.

The only way you would get an answer to this is if you ask the question
in a newsgroup specific to your system, and even then there's no
guarantee that it's possible.
 
K

Keith Thompson

Mark McIntyre said:
On Sun, 26 Dec 2004 20:20:15 +0100, in comp.lang.c , Steffen Fiksdal


The langauge itself guarantees that output will be either a valit pointer,
or a null pointer. If might later on be invalidated by a fault in your
code, but thats not C's fault... :)

I think you missed the "if output itself is garbage" part. malloc()
is irrelevant to the point.
 
K

Keith Thompson

infobahn said:
When you define a pointer, give it a valid value or assign NULL to it.
If its valid value ever becomes indeterminate, assign NULL to it
immediately (or give it another valid value). Ingrain this habit so
deeply into your programming that it becomes second nature.

When you have succeeded at this, all your pointers will either be
valid or NULL, so you can test them against NULL and know that, if
they are non-NULL, they are valid.

That's easier said than done:

ptr = malloc(whatever);
another_ptr = ptr;
...
free(ptr);
ptr = NULL;
/* ptr is safely null, another_ptr is indeterminate */
 
R

Robert

Keith said:
That's easier said than done:

ptr = malloc(whatever);
another_ptr = ptr;
...
free(ptr);
ptr = NULL;
/* ptr is safely null, another_ptr is indeterminate */

Nonetheless, is this considered best practice, i.e. initializing all
pointers to NULL, and assigning NULL to a pointer immediately after
calling free? And then preface every access with assert (ptr!=NULL);
???

-Robert
 
I

infobahn

Keith said:
That's easier said than done:

Quite so, but that doesn't mean it's impossible.
ptr = malloc(whatever);
another_ptr = ptr;
...
free(ptr);
ptr = NULL;
/* ptr is safely null, another_ptr is indeterminate */

another_ptr = NULL;
/* now another_ptr is safely null too. */

There's just no substitute for /knowing/ your code.
 
I

infobahn

Robert said:
Nonetheless, is this considered best practice, i.e. initializing all
pointers to NULL, and assigning NULL to a pointer immediately after
calling free? And then preface every access with assert (ptr!=NULL);
???

You'll only decide for yourself whether it's best practice after
you've had the opinions of a few people whose advice you know to
be accurate (you may not have made up your mind about me yet).

Nevertheless, my two cents: to avoid reading the "value" of an
indeterminate pointer certainly constitutes best practice! I see
no practical way of doing this except through ensuring that no
pointer ever has an indeterminate value for longer than is strictly
necessary. My "solution" would certainly guarantee this if only
it could be automated. :)

I'm not so sure about the assertion; I think that depends more on
what you're doing. Sometimes an assertion is the Right Thing, and
sometimes it isn't.

Keith Thompson did, however, raise the very important point that,
when one pointer becomes indeterminate, it may bring other pointers
down with it, and that's where you have to be very careful. It
doesn't make my solution unworkable, but it certainly makes it
harder to implement (and harder to automate).
 
R

Richard Bos

infobahn said:
another_ptr = NULL;
/* now another_ptr is safely null too. */

There's just no substitute for /knowing/ your code.

No shit, Sherlock. If you _knew_ your code, you wouldn't have to resort
to blind-flying tricks like setting pointers to null in the first place.

Richard
 
M

Michael Mair

Richard said:
No shit, Sherlock. If you _knew_ your code, you wouldn't have to resort
to blind-flying tricks like setting pointers to null in the first place.

Knowing your code is no guarantee for _not_ f.ing up somewhere,
inadvertently. As soon as you have a certain complexity, setting
pointers to NULL (*) and assert()ing elsewhere that you do not have
a null pointer may be a good idea to make sure that you did
at least this thing right and catch no uninitialised/invalidated
pointers.
[ (*) Nobody prevents you to use <assert.h> and NDEBUG. ]

Only if you rely on this saving you from every possible evil, then
you are in deep trouble.

However, I usually only initialise pointers with NULL. Even though
I am rather a belt and braces type ;-)


Cheers
Michael
 
K

Keith Thompson

infobahn said:
You'll only decide for yourself whether it's best practice after
you've had the opinions of a few people whose advice you know to
be accurate (you may not have made up your mind about me yet).

Nevertheless, my two cents: to avoid reading the "value" of an
indeterminate pointer certainly constitutes best practice! I see
no practical way of doing this except through ensuring that no
pointer ever has an indeterminate value for longer than is strictly
necessary. My "solution" would certainly guarantee this if only
it could be automated. :)

If a pointer becomes indeterminate and you later refer to its value,
your program has a bug.

If a pointer becomes indeterminate, you set it to NULL, and then you
later refer to its value, your program probably still has a bug.
You've merely made the consequences of the bug slightly more
predictable and/or detectable (though you could still invoke undefined
behavior if you dereference it rather than just referring to its
value).
 
S

Steffen Fiksdal

When you define a pointer, give it a valid value or assign NULL to it.
If its valid value ever becomes indeterminate, assign NULL to it
immediately (or give it another valid value). Ingrain this habit so
deeply into your programming that it becomes second nature.

When you have succeeded at this, all your pointers will either be
valid or NULL, so you can test them against NULL and know that, if
they are non-NULL, they are valid.

Well, I don't program for those calling my API......
 
R

Richard Bos

infobahn said:
When you define a pointer, give it a valid value or assign NULL to it.
If its valid value ever becomes indeterminate, assign NULL to it
immediately (or give it another valid value). Ingrain this habit so
deeply into your programming that it becomes second nature.

When you have succeeded at this, all your pointers will either be
valid or NULL, so you can test them against NULL and know that, if
they are non-NULL, they are valid.

Apart from the dubious nature of this trick in general, how does it help
the OP at all, who specifically asked about

That is, how do you distinguish between a pointer to a simple,
non-allocated object, which is neither null nor invalid, and a random
integer cast to a pointer, which isn't null, but very likely _is_
invalid?

Richard
 
D

dandelion

That is, how do you distinguish between a pointer to a simple,
non-allocated*) object, which is neither null nor invalid, and a random
integer cast to a pointer, which isn't null, but very likely _is_
invalid?

If anyone is able to answer that (apart from "You can't", of course)
i'd be highly interested.

Personally, i'd say there is no portable, platform independent way to do
this. And even non-portable, platform-dependent, i do not know any
bullet-proof ways of doing that.

I would be one h*ll of a debugging tool.

*) I take it you mean non-malloc'ed.
 
I

infobahn

Keith said:
If a pointer becomes indeterminate and you later refer to its value,
your program has a bug.
Indeed.


If a pointer becomes indeterminate, you set it to NULL, and then you
later refer to its value, your program probably still has a bug.
You've merely made the consequences of the bug slightly more
predictable and/or detectable (though you could still invoke undefined
behavior if you dereference it rather than just referring to its
value).

Indeed. If you were simply rephrasing and making explicit the
information I tried to convey, I thank you for it. If you are
trying to disagree with me, however, I think you failed.
 
I

infobahn

Richard said:
No shit, Sherlock.

Scatology is so often a substitute for thoughtfulness. I hope that isn't
the case here.
> If you _knew_ your code, you wouldn't have to resort
to blind-flying tricks like setting pointers to null in the first place.

I think you've missed the point. Many programs are large and complex,
and consequently difficult to "know" completely, and you appear to
recognise this fact. Nevertheless, one can know one's code
/sufficiently/ to be aware of whether or not one's code is likely
to have more than one pointer pointing into the same object, and
consequently to be aware of just how much is involved in ensuring
that one does not overlook a dangling pointer.

But please - if you feel it necessary to use offensive language
in your reply, would you be so kind as to change the subject
line in some way, so that I am forewarned not to read that reply?

Thanks.
 

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,157
Messages
2,570,879
Members
47,413
Latest member
KeiraLight

Latest Threads

Top