Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do any implementations of operator new return a pointer to a guard page for zero-size arrays?

Related to: C++ new int[0] -- will it allocate memory?

The standard says, in 5.3.4/7:

When the value of the expression in a direct-new-declarator is zero, the allocation function is called to allocate an array with no elements.

...and, in 3.7.3.1/2:

The effect of dereferencing a pointer returned as a request for zero size is undefined.

...yet, the pointer can't be a null pointer.

Since actually dereferencing the pointer is undefined behavior, does any implementation return a pointer to a guard page? I imagine that it'd be easy, and help detect bugs/improve security.

like image 585
Alexander Riccio Avatar asked Jul 22 '15 22:07

Alexander Riccio


People also ask

What happens when we use new and delete operator?

Memory that is dynamically allocated using the new operator can be freed using the delete operator. The delete operator calls the operator delete function, which frees memory back to the available pool. Using the delete operator also causes the class destructor (if one exists) to be called.

What is the use of new and delete operators in C++?

In C++, you can allocate memory at runtime using the “new” operator. Once you no longer need to use the variable that you have declared dynamically, you can deallocate the memory occupied by the variable using the “delete” operator in C++.

Why is new and delete used?

The main difference between new and delete operator in C++ is that new is used to allocate memory for an object or an array while, delete is used to deallocate the memory allocated using the new operator. There are two types of memory as static and dynamic memory.

How you can use new and delete keyword for dynamic memory allocation?

Examples: delete p; delete q; To free the dynamically allocated array pointed by pointer-variable, use the following form of delete: // Release block of memory // pointed by pointer-variable delete[] pointer-variable; Example: // It will free the entire array // pointed by p.


2 Answers

I looked at the (draft) standard and I couldn't find anything that explicitly prohibits this. I would guess that the answer is "no", though. This is why:

  • As you say, new is required to return a non-null pointer.
  • Further, whatever it returns must be safe to pass to delete.
  • So a "random value" won't work because it will break delete.
  • It's also required to return different values for each call (at least until they are deleted) - see the C++ standard section basic.stc.dynamic.allocation.
  • At this point only one option remains: return "fake pointers" which are somehow recognizable by delete as "fake pointers".

One possible implementation could be done by reserving a range of unpaged memory, and every time someone calls new int[0] it could return a different address in that range (easy to do if the allocator keeps a global counter or something like that).

On the plus side, you will gain the ability to immediately detect dereferences on this type of pointer. On the other hand, you will lose the ability to detect double-frees because delete on your pointer effectively becomes a no op, and you will make new and delete more complex and slower for all the normal cases.

So because it's tricky to do, and the cons outweigh the pros, I'm pretty confident that nobody does that.

gcc on linux just allocates a small amount of memory and returns that. I believe that this is pretty much a standard way to do this.

like image 67
AaronI Avatar answered Oct 02 '22 17:10

AaronI


To track how much memory needs to be released most allocators I've looked within or wrote look something like:

 void *malloc_example( size_t bytes ) {
     size_t *ret = get_memory(bytes + sizeof size_t);   /* find free memory */
     *ret = bytes;                /* remember size of allocated area */
     return (void *)( ret + 1 );
 }

So when you allocate zero-length blocks you actually get a sneaky word ahead of the address returned to you. This also assures each allocation is assigned a unique address. This is important and pointing to dedicated guard memory for zero-length blocks is more of a waste as each free must test for what my experience says is a rare condition.

Some debugging allocators include additional overhead to catch double-frees, memory leaks, guard words to catch overflow of previous buffers, etc. Also, pointing to some magic memory can make such debugging more difficult to do.

like image 27
Gilbert Avatar answered Oct 02 '22 16:10

Gilbert