Testing if a pointer is valid

I

Ian Collins

I can easily provide a "safe malloc" that aborts on allocation
failure. If for some reason we don't want it to be dependent on
malloc, the user can pass it a memory area from which to do
allocations.

I can't provide a gc_malloc. The problem is you have to do periodic
sweeps of the memory managed by the program, to detect pointers to
allocated blocks. You then put any orphaned blocks back on the free
list. There's no way of doing that without altering the compiler
itself.

There is, it's called a library. If I compile with

cc x.c

The executable uses malloc from libC.

If I compile with

cc x.c -lgc

The executable uses malloc from libgc. Loading initialises the sweeper
thread.
 
S

Seebs

You almost seem to be implying that only incompetent programmers
make mistakes. I think what you really mean is that only incompetent
programmes make *certain kinds* of mistakes -- but I think that's
unrealistic.

For better or worse, I make a LOT of the kinds of mistakes that "only"
incompetent programmers make. I have fairly extreme ADHD, and the functional
upshot is that I can do a lot of things that are too hard for most people to
even attempt, but I can't do a lot of things that they take for granted,
because my brain simply *won't stay focused long enough* if a task isn't
Really Hard. If something isn't compelling enough to draw my whole attention
to it, I'm off thinking about unrelated things within a second or two.

This can be really useful, but it can also be very disruptive. Net result,
I can write something interesting and nontrivial in which the only errors
are mismatched ()s, missing semicolons, and format strings without their
corresponding arguments -- the logic is fine on the first try. :)

-s
 
S

Seebs

If the hypothetical doesn't specify that, there's no reason for me to
assume it.

Well, that's the thing. Many of the bugs I see are *hard* to reproduce.

I once had a bug which could be reproduced only if:

* You had a set of prebuilt compilation tools from two weeks ago.
* You had a source tree containing a recent update to one of those
tools.
* You had a prebuilt compilation tool other than that tool which did
*not* need to be rebuilt.
* That compilation tool had an RPATH setting that used $ORIGIN.
* That tool's name was under four characters.

Not the sort of thing one usually has in the list of sanity tests.

-s
 
S

Seebs

Have you also had an appraisal where your manager looks at your
last year's work, and informs you that you had a massively negative
productivity, as measured by lines of code?

I haven't, but I probably will if he ever sees that post, because he's
got that kind of sense of humor.
u32 getBit(u32 v, int b)
{
int i;
u32 m=1;
for(i=1; i<b; ++i) {
m<<=1;
}
v&=m;
return v;
}

That... is a thing of beauty. Doesn't it just make you wish that you'd
been able to see the multiple attempts to get it to work correctly? I'd
put five bucks on it originally having been "i=0" as the loop initializer.

-s
 
B

Ben Bacarisse

Seebs said:
I haven't, but I probably will if he ever sees that post, because he's
got that kind of sense of humor.


That... is a thing of beauty. Doesn't it just make you wish that you'd
been able to see the multiple attempts to get it to work correctly? I'd
put five bucks on it originally having been "i=0" as the loop
initializer.

I once saw some code that had to tabulate a function and it's inverse.
Both were permutations of the integers in the range 0..(N-1):

for (int x = 0; x < N; x++)
function_table[x] = /* relatively complex code */;

The inverse was not computable but, hey, we have a table of the function
so we can search it:

for (int y = 0; y < N; y++)
/* find x such that f(x) = y */
for (int x = 0; x < N; x++)
if (function_table[x] == y)
inverse_table[y] = x;
 
W

websnarf

Richard, you seem to believe that a library should validate all
the pointers passed into it.  Can you explain how you believe
that a library should actually do this?  I don't believe that it
is practical.

Well, if you are in control of the compiler and its libraries, then
you can typically get very close. Close enough for the typical
purpose anyway (which is to debug something). In Windows programs,
you have a finite number of "segments" that you program loads, plus a
some dynamic memory that can be allocated from the system, that you
can obviously track in a linked list (or balanced tree if you want
more speed) of regions. The "rough range" for all such regions can be
estimated by the behavior of Windows, its libraries and so on.

I have actually implemented similar utilities in the old DOS days to
debug some nasty code. In practice it works just fine. Even
estimates, like testing for double frees, allocation canaries, and
{min, max} memory regions is usually good enough.
 
P

Phil Carmody

Seebs said:
I haven't, but I probably will if he ever sees that post, because he's
got that kind of sense of humor.


That... is a thing of beauty. Doesn't it just make you wish that you'd
been able to see the multiple attempts to get it to work correctly? I'd
put five bucks on it originally having been "i=0" as the loop initializer.

That's why I remember it almost verbatim. Out by one in a loop which did
something that could be done in one swell foop; thus displaying a knowledge
of the <<= operator, yet apparently know understanding of the << operator.

You owe me 5 bucks - the i=1 was causing lines to not be allocated in
the multiplexer, which was causing customers (when they could get
lines) to complain about poor service. Finding that, as you say, thing
of beauty made the bugfix one of the most fun I've ever done. However,
at only 10 lines removed code, it wasn't very good for my negative
productivity, as that was several days' work.

Phil
 
P

Phil Carmody

Ben Bacarisse said:
Seebs said:
I haven't, but I probably will if he ever sees that post, because he's
got that kind of sense of humor.


That... is a thing of beauty. Doesn't it just make you wish that you'd
been able to see the multiple attempts to get it to work correctly? I'd
put five bucks on it originally having been "i=0" as the loop
initializer.

I once saw some code that had to tabulate a function and it's inverse.
Both were permutations of the integers in the range 0..(N-1):

for (int x = 0; x < N; x++)
function_table[x] = /* relatively complex code */;

The inverse was not computable but, hey, we have a table of the function
so we can search it:

for (int y = 0; y < N; y++)
/* find x such that f(x) = y */
for (int x = 0; x < N; x++)
if (function_table[x] == y)
inverse_table[y] = x;

"What are you laughing at?" my g/f asks - and 30s later she's
laughing too, and she's not even a programmer.

Again, a thing of beauty, something that displays a some shallow
insight and yet the complete inability to see the obvious next step.

Phil
 
B

Ben Bacarisse

Phil Carmody said:
Ben Bacarisse <[email protected]> writes:
I once saw some code that had to tabulate a function and it's inverse.
Both were permutations of the integers in the range 0..(N-1):

for (int x = 0; x < N; x++)
function_table[x] = /* relatively complex code */;

The inverse was not computable but, hey, we have a table of the function
so we can search it:

for (int y = 0; y < N; y++)
/* find x such that f(x) = y */
for (int x = 0; x < N; x++)
if (function_table[x] == y)
inverse_table[y] = x;

"What are you laughing at?" my g/f asks - and 30s later she's
laughing too, and she's not even a programmer.

Again, a thing of beauty, something that displays a some shallow
insight and yet the complete inability to see the obvious next step.

The twist (if you can call it that) is that there was absolutely no need
to change the code. The tables were calculated only once and were not
large (a few hundred elements, I think) but the subsequent calculation
was very expensive, so the cost of this initialisation was almost
unmeasurable. I did change it though. I had to be able to sleep.
 
M

Michael Press

Phil Carmody said:
Stop trying to be clever; do you not think I chose that word
for a reason? However, I should be flattered that you interpreted
what I wrote as it was intended, which is so rare nowadays, even
if you didn't work out my motivation for such wording.

However, one cannot have an argument *without* some assertions.
Call them axioms, call them postlates, call them whatever, but
they are not argued, they are asserted.

Is it time to recognize that you did not assert
consequences of dereferencability of a pointer
to its validity?
 
N

Nick Keighley

Really?  I've yet to see one that does, the overhead would be dramatic
for large blocks.  Not to mention knowing how to link a different free
from the standard library for debugging.

I'm pretty sure Visual C++ in debug mode writes over at least some of
the block when its freed. Finding feeefeee in your data indicates
you've accessed a freed block
 
M

Malcolm McLean

I'm pretty sure Visual C++ in debug mode writes over at least some of
the block when its freed. Finding feeefeee in your data indicates
you've accessed a freed block
Most systems crunch your garbage in debug mode, also set new blocks
allocated with malloc to some bit pattern that results in an invalid
pointer if interpreted as an address and a large negative number if
interpreted as an integer.

The overhead is large in terms of malloc(), free, but not in terms of
the program. If a program doesn't write to practically all of the
memory it allocates, then what is it doing with it?
 
N

Nick Keighley

(e-mail address removed) (Richard Harter) writes:

[...]
Any language in which it is possible for a pointer to be invalid but
which provides no way to test for validity is fundamentally flawed.

What existing language has pointers and is not "fundamentally flawed"?

Pascal?
Which has its flaw in the Pascal equivalent of union, but not I
believe in its pointers.
 
K

Keith Thompson

Nick Keighley said:
(e-mail address removed) (Richard Harter) writes:

[...]
Any language in which it is possible for a pointer to be invalid but
which provides no way to test for validity is fundamentally flawed.

What existing language has pointers and is not "fundamentally flawed"?

Pascal?
Which has its flaw in the Pascal equivalent of union, but not I
believe in its pointers.

Maybe. Some versions of Pascal do have the ability to take the
address of a variable; I don't know whether there's such a feature
in the latest standard.

But I'm reasonably sure Pascal lets you allocate a pointer, create
a copy of it, and deallocate the original, resulting in a dangling
pointer value -- and I don't know of a standard way to detect this.
I think that makes Pascal "fatally flawed" by Richard's definition.
 
N

Nick Keighley

jacob navia wrote:
) Le 20/09/11 22:35, Willem a ?crit :

)> Given the average programmer I come across, I prefer the first.
)>
)> Or, to put it bluntly: in the Real World(tm), most programmers are
)> a bunch of hacks, who write crap code, so the invention of a language
)> that takes away responsibility from them is a Good Thing(tm).
)
) What bothers me of those would be managers I have come across (you are

Try again.  I'm a maintenance programmer.  In other words: I fix the mess
that those hacks leave behind.  In the caste system, which you seem so
proud of,

um. I think he was being sarcastic. Jacob *disapproves* of the so-
called caste system. Whilst he has a point that programmign gets
deskilled by being chopped up and micro-managed. It is also a fact
that there are a lot of poor programmers out there and a lot of crap
code.

Deskilling and micro-management won't fix this of course.
 
N

Nick Keighley

August Karlstrom wrote:

This has absolutely nothing to do with "macho programmer attitude", whatever
that is.  If a person is employed as a technician, or at least intends to do
work in that field, then the least that person is expected to do is to have
a rudimentary understanding of how the tools of the trade work and what are
the proper ways of using them.  If the would-be technician fails to have a
basic understanding how his tools of the trade work then he simply cannot
shift the blame of writing broken code anywhere else beyond his failure of
attaining a basic understanding on how his tools of the trade work,

where I come from there is an aphorism "A bad workman blames his
tools". personnally I think this is slightly flawed. A good workman
makes sure he has the best tools. he can *manage* with poor tools,
better than the bad workman. But he knows his tools are inadequate.
which includes accusing the tool of being unsafe.

it isn't a pejorative term. C, by design, gives you less protection
than some languages.
In this case, you tried to claim that C is unsafe by presenting code which
was broken by violating a very basic aspect of how C works, one which is
taught at the very beginning of any introductory course.  Yet, even though
the problem with your example lies precisely in an inability to write valid
code, you tried to pass it off as a fundamental problem affecting the entire
programming language. This isn't a sensible thing to do.  

If you actually cared for that problem then you would had invested time to
try to understand what were [its] causes.  This would quickly lead you to the
way an object's lifetime is defined in the C programming language, which
would be enough to understand that the problem resided in the code and not
the language.  You could also come to the conclusion that failing to throw a
warning when a local variable is referenced beyond it's life time, or
running similar diagnostics, is a compiler issue, not a language issue.  
This is something which has been done before[1].  Yet, you failed to
consider any of this options and instead you opted to accuse the language
of, in a way, being fundamentally broken.  This is a problem caused by
nothing more than a willingness to shift blame and responsibilities, not by
"typical macho programmer attitude", and throwing baseless accusations
around does nothing to fix whatever problem there may exist.

[1]http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14156

I'd have snipped the above if you din't moan about snipping
 
N

Nick Keighley

This is is priceless.  I've seen this sort of phrase a lot lately (on Usenet).

Hint: If you don't know what something is, you can hardly make any
statements about it - including the statement of denial (as above).


You need to go back and re-read what I wrote about dynamite.

Again, no one is saying that "unsafe" == bad.

AOL- me too
 
N

Nick Keighley

How can a local variable live after the function has returned?

in some languages everything is (potentially) dynamic. Something that
was created locally may be returned.
But a garbage collector handles dynamically allocated objects, not local
variables.

not all languages distinguish them in the same way.
 
N

Nick Keighley

As far as this hypothetical language (which doesn't seem so hypothetical
now that I've seen other people cite similar real ones)

my thoughts were of scheme

(define (f)
(let ((y '(red blue green))) ; 'local' variable
(set! x y) ))

(define x 0)
(display x)
(f)
(display x)

--
displays: 0 (red blue green)

It could be argued that is simply an assignment but the rbg list is
the nearest schem has to a data structure. And more complex examples
would show you can hack 'local' variables outside of the function. And
even re-enter the function!
 

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

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,286
Latest member
ChristieSo

Latest Threads

Top