C pointers 
Author Message
 C pointers

Quote:


> > However, you can
> > only (safely) compare an initialized pointer with NULL and other
> > pointers to the same object.
> Do you mean the following isn't safe?
> int i, j;
> int *p = &i;  /* initialized pointer */
> p != &j;      /* compare to a pointer to a different object */

Yes.

i and j are separate objects. An implementation may have implemented the
'stack' in multiple zones, and decide to locate separate objects like
i and j in different zones. It may also decide to implement pointer
comparison only within one zone. This would mean your example would be
unsafe on such a compiler.

I'm not actually aware of a compiler doing exactly this, but similar
problems arise with segmented memory, shared memory, etc. So don't
do the above.

Michiel Salters
--



Thu, 13 Feb 2003 03:00:00 GMT  
 C pointers

Quote:

> > However, you can
> > only (safely) compare an initialized pointer with NULL and other
> > pointers to the same object.

> Do you mean the following isn't safe?

> int i, j;
> int *p = &i;  /* initialized pointer */
> p != &j;      /* compare to a pointer to a different object */

Yes, I think it is, but it doesn't answer the original question; all you
know is that this pointer is not the same as that pointer. It doesn't
even tell you whether this pointer is in the same object as that pointer
(and there's no way, AFAIK, to find this out); it certainly doesn't tell
you whether either of these is valid. In fact, an invalid pointer can
compare equal, unequal, or mu-equal to any other pointer, because
comparing it with anything invokes undefined behaviour.

Richard
--



Thu, 13 Feb 2003 03:00:00 GMT  
 C pointers

Quote:


> > However, you can
> > only (safely) compare an initialized pointer with NULL and other
> > pointers to the same object.
> Do you mean the following isn't safe?
> int i, j;
> int *p = &i;  /* initialized pointer */
> p != &j;      /* compare to a pointer to a different object */

That's okay -- Salters wasn't quite correct.
*Relational* comparisons of pointers (<, <=, >=, >)
are allowed only between pointers within the same object
(or just past its end), but *equality* testing is allowed
for any valid pointers.  (A pointer is not valid until
properly initialized as a null pointer, a pointer within
an actual object, or pointing just past the end of an
object.  And if the object lifetime has expired, any
pointer based on that object becomes invalid.)
--



Thu, 13 Feb 2003 03:00:00 GMT  
 C pointers
Many thanks to everybody for the answers.
I was afraid this was the case, I just wanted to be sure I hadn't
fogotten or overseen something (or that someone bright hadn't
developped some great tool  -hint, hint - behind my back).

Anyway, thanks

  Serge

Da Big Book quoteth on 24 Aug 2000 15:03:06 GMT, famous Monk

Quote:


> > I have a small question:  assuming you have a function which gets a
> > pointer as parameter.

> > Is there a means to check and make sure the pointer has been
> > allocated?
> > Is there a means to check _how much space_ has been allocated to this
> > pointer?

> No, and no. Alas.

> Richard
> --


------------------------------------------------------------------------------
  The opinions expressed are mine and none other's
------------------------------------------------------------------------------
Serge Marelli

--



Thu, 13 Feb 2003 03:00:00 GMT  
 C pointers

Quote:

> Serge *Anonymous Coward* Marelli


> > I have a small question:  assuming you have a function which gets a
> > pointer as parameter.

> > Is there a means to check and make sure the pointer has been
> > allocated?

> No.

> > Is there a means to check _how much space_ has been allocated to this
> > pointer?

> No.

> The above to answers apply to standard C.  Your compiler and C library of
> course include implementations that may provide this information.  They will
> not provide it through standard C library functions.  It is, of course,
> possible in debug builds to redefine malloc via a macro to another function
> that adds this information to a nice little convenient list and returns it
> when asked.  But this assumes that you've got access to all source code that
> allocates memory.  If you're using something like strdup'ed strings, or any
> third party library that allocates memory, this won't work.  It's also a lot
> of complexity for debug code, and may end up with its own bugs.... what a
> mess!

Also remember that not all pointers come from malloc.  Some may be
pointers to static data, or pointers to temporary variables, or
they may be derived from malloc'ed pointers, but not point to the
beginning of the malloc'ed space.

So not only is there no standard way of doing this, but there's no
non-standard way of doing it completely reliably, either.

/peter
--



Thu, 13 Feb 2003 03:00:00 GMT  
 C pointers

Quote:
Marelli) writes:

[...snip...]

Quote:
> Is there a means to check and make sure the pointer has been
> allocated?

[...snip...]

I get the OP's meaning I believe (he wants to know how to check that a
pointer has been initialised to point to a valid memory address).

Is Serge's usage here common ? Is it OK?

I had to read it twice to understand what he meant, which I don't
like. On the other hand, _my_ wording seems a bit ... cumbersome
:-). On the first hand again you could conceivably have an array of
handles allocated on the heap, i.e. the space for the pointers
themselves needs to be allocated, so it _is_ possible to read Serge's
sentence literally.

(In this specific case however, when the pointer is received as an
argument to a function, it obviously has to exist) .
--
H?kon Alstadheim, Montreal, Quebec, Canada  
--



Thu, 13 Feb 2003 03:00:00 GMT  
 C pointers

Quote:



> > > However, you can
> > > only (safely) compare an initialized pointer with NULL and other
> > > pointers to the same object.
> > Do you mean the following isn't safe?
> > int i, j;
> > int *p = &i;  /* initialized pointer */
> > p != &j;      /* compare to a pointer to a different object */
> Yes.
> i and j are separate objects. An implementation may have implemented the
> 'stack' in multiple zones, and decide to locate separate objects like
> i and j in different zones. It may also decide to implement pointer
> comparison only within one zone. This would mean your example would be
> unsafe on such a compiler.
> I'm not actually aware of a compiler doing exactly this, but similar
> problems arise with segmented memory, shared memory, etc. So don't
> do the above.

Mistake, I now see.

I should have been more precise and specify what compare meant, namely
< > <= and >=, in which case I wouldn't have fell in the trap later, when
I included != from Kalle's example. != and == are indeed safe and sound
when both operands are valid pointers (to NULL, objects, members of objects,
or one beyond the last of an array). I guess that includes the C99
structure hack, when a pointer can point to one beyond the last element
of the variable array.

What I sketched for zones etc. still holds for the < > <= and => operators.

Michiel Salters
--



Fri, 14 Feb 2003 03:00:00 GMT  
 C pointers

Quote:
> I have a small question:  assuming you have a function which gets a
> pointer as parameter.
> Is there a means to check and make sure the pointer has been
> allocated?
> Is there a means to check _how much space_ has been allocated to this
> pointer?

You could write a wrapper around malloc and friends, and keep a
log of successfull allocations which have not yet been freed. By searching
for your pointer in this log, you can tell if it was returned by your
malloc wrapper.

Using a few preprocessor tricks, you can replace malloc and friends with
your wrappers and keep the same names, so you only have to recompile.

(Or can you... Is this conforming?)

---- mymalloc.h ---

#include <stdlib.h>

#undef malloc    /* In case it's a macro. */
#define malloc(s) my_malloc(s,__FILE__,__LINE__)
extern void* my_malloc(size_t s, char*file, unsigned long line);

/* Same for calloc, free, and realloc. */

----- mymalloc.c ----

#include <stdlib.h>
/* Look, this file does not include "mymalloc.h" */

void* my_malloc(size_t s, char *file, unsigned long line)
{
   void *ptr=malloc(s);

   if (ptr)
   {
       /* Keep a log of ptr, s, file and line. */
       return ptr;
   }
   else
   {
       return NULL;
   }

Quote:
}  

/* Same for calloc, free and realloc. */
-----------------------------------------------

This type of code also makes a good memory leak detector. The more
adventurous of you may also want to increase the allocation by a few
bytes either side and check for buffer overflow/underflow when you come
to free it.

You could also modify this technique if you are porting some not
compliant code which relies on memory to still be usable after a free
but before the next malloc. On free, save the pointer. When malloc
is called, first go through the saved pointers, free'ing each one in
turn.

Bill, pointless.
--



Tue, 18 Feb 2003 12:49:02 GMT  
 C pointers

Quote:

> Serge *Anonymous Coward* Marelli is of the opinion:
>> I have a small question:  assuming you have a function which gets a
>> pointer as parameter.
>> Is there a means to check and make sure the pointer has been
>> allocated?

> Not in general.  I guess for a system that has signals you could help
> check by setting up a SIGSEGV handler and try writing to the pointer,
> but that is likely to be very unpleasant if you're not supposed to be
> changing valid data there...

You don't need to write to the location pointed to by the pointer;
simply attempting to dereference it would be enough to trigger the
SIGSEGV.

I recently had to do just this for some library code that serviced
requests from a debugging process.  A control thread in the process
receives messages from the de{*filter*} requesting an item of data from some
arbitrary address in the process's virtual address space.  The function
that services this request has to check, before attempting to read the
data, that accessing the address is not going to crash the process.

The code to do this is below.  I apologise that it's UNIX-specific, but
it might help the OP if he is using a UNIX platform; and it may exhibit
some features of general C interest. :-)  Of course, merely determining
that an address can be read from safely does not mean that it lies
within allocated memory.

#include <setjmp.h>
#include <signal.h>

static jmp_buf segvbuf;

/**********************************************************************
 * Private function to catch segment violations caused by attempt to
 * access out of range address in valid_addr().  The function longjumps
 * back into valid_addr() with the value 1 indicating that the signal
 * was received.
 *
 * The parameter sig is ignored - SIGSEGV is assumed.
 **********************************************************************/
static void
sig_catcher(int sig)
{
    longjmp(segvbuf, 1);

Quote:
}

/**********************************************************************
 * Private function to validate a virtual address.  The function sets a
 * signal handler to catch SIGSEGV, then attempts to dereference the
 * address addr.  If addr is outside the allocated virtual address space
 * for this process, the signal handler will return a value (via
 * longjmp()) to indicate that it was called; otherwise, we assume the
 * address is valid.
 *
 * Returns 1 if address is valid, 0 otherwise.
 **********************************************************************/
static int
valid_addr(void *addr)
{
    void (*savefunc)(); /* SIGSEGV state hold area */
    int valid;

    /* Set up the signal handler */
    savefunc = signal(SIGSEGV, sig_catcher);

    if (setjmp(segvbuf))
    {
        /* Only reach here via longjmp() from signal catcher - i.e. we
         * had a SIGSEGV, so addr is invalid.
         */
        valid = 0;
    }
    else
    {
        /* Attempt to dereference the address.  (NB. Since we're not
         * assigning the result anywhere, the volatile qualifier is
         * included in the cast to prevent the compiler from removing
         * this entire expression through optimisation.)
         */
        *((volatile char *) addr);
        /* Reach here if the above dereference didn't cause a SIGSEGV -
         * i.e. addr is valid.
         */
        valid = 1;
    }

    /* Restore SIGSEGV to previous condition. */
    (void) signal(SIGSEGV, savefunc);

    return valid;

Quote:
}

--
Phil Reynolds                   http://www.*-*-*.com/
Remove "spamaway." if replying by mail
--



Wed, 19 Feb 2003 00:42:45 GMT  
 
 [ 26 post ]  Go to page: [1] [2]

 Relevant Pages 
 

 
Powered by phpBB® Forum Software