0

I'm making a dynamic memory allocator and I need to check than when I'm freeing a section of it, that the pointer I'm passing into the function is in fact within that area. I have a pointer to the beginning of the malloc'd area

typedef unsigned char byte;

static byte *memory // pointer to start of allocator memory

which I assign in my initiating function. I also have the size of the malloc'd area stored in

static u_int33_t memory_size;   // number of bytes malloc'd in memory[]

How do I ensure that the ptr isnt... (in pseudo code)

ptr < *memory || ptr > *memory + memory_size

and that code results in the following error;

error: comparison of distinct pointer types lacks a cast [-Werror] if ( object < memory || object > (memory + memory_size)) ^

I'm not sure what I need to cast and what not to...

The free function is as follows...

void memfree(void *object)
{
   if ( object < memory || object > (memory + memory_size)) {
  fprintf(stderr, "vlad_free: Attempt to free via invalid pointer\n");
  exit(EXIT_FAILURE);
   }
}
qruton
  • 33
  • 6
  • This seems to be a duplicate of: http://stackoverflow.com/questions/3065092/check-if-a-pointer-points-to-allocated-memory-on-the-heap – Jaime Aug 26 '16 at 05:31
  • So, your dynamic allocator has a single reservoir of memory to allocate, which is necessarily all contiguous? What is the type of `byte`? What is the type of `u_int33_t`? What goes wrong with the expression you propose? How portable does your code have to be? – Jonathan Leffler Aug 26 '16 at 05:32
  • @Jaime: I think the question you reference is more general than the problem posed in this question. – Jonathan Leffler Aug 26 '16 at 05:33
  • sorry, typedef unsigned char byte; and portability isn't a concern – qruton Aug 26 '16 at 05:35
  • In future, please add requested information to the question — you can edit your own question. I've added the typedef for `byte` for you. – Jonathan Leffler Aug 26 '16 at 05:38
  • None of this makes much sense. Are you trying to write your own malloc or something? – Lundin Aug 26 '16 at 06:14

1 Answers1

0

Original

This is wrong as pointed out by Raymond Chen's answer

void memfree(void *_object)
{
   byte* object = (byte*)_object;
   if ( object >= memory && object < (memory + memory_size)) {
       /* defined guarantees - they happened to be in the same object. */
   } else {
      fprintf(stderr, "memfree: Attempt to free via invalid pointer\n");
      exit(EXIT_FAILURE);
   }
}

The types of pointers need to be the same. Given that you seem to have a range in bytes, it seems best to use byte.

From the C standard n1570

When two pointers are compared, the result depends on the relative locations in the address space of the objects pointed to. If two pointers to object types both point to the same object, or both point one past the last element of the same array object, they compare equal. If the objects pointed to are members of the same aggregate object, pointers to structure members declared later compare greater than pointers to members declared earlier in the structure, and pointers to array elements with larger subscript values compare greater than pointers to elements of the same array with lower subscript values. All pointers to members of the same union object compare equal. If the expression P points to an element of an array object and the expression Q points to the last element of the same array object, the pointer expression Q+1 compares greater than P. In all other cases, the behavior is undefined.

Here, I believe the undefined behavior, is that you can't tell if on 2 systems, that there will be a consistent ordering, so code which uses a < b, may be true on some systems and false on others.

New answer

Use

void memfree(void *_object)
{
   uintptr_t object = (uintptr_t)_object;
   if ( object >= (uintptr_t)memory && object < ((uintptr_t)memory + (uintptr_t)memory_size)) {
       /* defined guarantees - they happened to be in the same object. */
   } else {
      fprintf(stderr, "memfree: Attempt to free via invalid pointer\n");
      exit(EXIT_FAILURE);
   }
}
Community
  • 1
  • 1
mksteve
  • 12,614
  • 3
  • 28
  • 50
  • 1
    Comparing pointers, using relational operators, that don't belong to the same object is undefined behavior. – 2501 Aug 26 '16 at 06:06
  • Your edit implies as if the behavior is consistent on separate architectures. It isn't, and the result isn't false or true, it is simply undefined. – 2501 Aug 26 '16 at 06:48
  • Understood - that you are representing the consensus in stack overflow, but I can't believe this is what was meant by the designers of the language, in fact if it is possible to have a pointer which happens to point within the bounds, then other rules will be false (conversion to and from different types doesn't affect the value of the pointer). So I believe my interpretation is correct – mksteve Aug 26 '16 at 06:56
  • The last line of the standard is very clear: *in all other cases, the behavior is undefined*, which is what happens if a pointer that doesn't point to object memory, is passed to memfree. – 2501 Aug 26 '16 at 07:18