I read Are negative array indexes allowed in C? and found it interesting that negative values can be used for the index of an array. I tried it again with the c++11 unique_ptr and it works there as well! Of course the deleter must be replaced with something which can delete the original array. Here is what it looks like:
#include <iostream>
#include <memory>
int main()
{
const int min = -23; // the smaller valid index
const int max = -21; // the highest valid index
const auto deleter = [min](char* p)
{
delete [](p+min);
};
std::unique_ptr<char[],decltype(deleter)> up(new char[max-min+1] - min, deleter);
// this works as expected
up[-23] = 'h'; up[-22] = 'i'; up[-21] = 0;
std::cout << (up.get()-23) << '\n'; // outputs:hi
}
I’m wondering if there is a very, very small chance that there is a memory leak. The address of the memory created on the heap (new char[max-min+1]) could overflow when adding 23 to it and become a null pointer. Subtracting 23 still yields the array’s original address, but the unique_ptr may recognize it as a null pointer. The unique_ptr may not delete it because it’s null.
So, is there a chance that the previous code will leak memory or does the smart pointer behave in a way which makes it safe?
Note: I wouldn’t actually use this in actual code; I’m just interested in how it would behave.
Edit: icepack brings up an interesting point, namely that there are only two valid pointer values that are allowed in pointer arithmetic:
§5.7 [expr.add] p5As such, the
new char[N] - minof your code already invokes UB.Now, on most implementations, this will not cause problems. The destructor of
std::unique_ptr, however, will (pre-edit answer from here on out):§20.7.1.2.2 [unique.ptr.single.dtor] p2So yes, there is a chance that you will leak memory here if it indeed maps to whatever value represents the null pointer value (most likely
0, but not necessarily). And yes, I know this is the one for single objects, but the array one behaves exactly the same:§20.7.1.3 [unique.ptr.runtime] p2And there is no description for the destructor.