Reputation: 401
I recently came across a C++ class that implements a non zero index based array. I.e. one could initialize this class to have a valid index range of say 15..19. This class calculates the adress for the element with index 0, even though this probably is outside of allocated address space and stores that adress. Element access is then just handled via operator[] using this element 0 address. Some example code (simplified):
template <typename T>
class NonZeroArray
{
public:
NonZeroArray(int min_index, int size, T default_element) :
m_min_index(min_index),
m_size(size),
m_default_element(default_element)
{
m_base_address = (T*) malloc(size*sizeof(T));
m_zero_index_adress = m_base_address - min_index;
}
~NonZeroArray()
{
free(m_base_address);
}
T& element(int index)
{
if ( index < m_min_index || index >= m_min_index + m_size)
return m_default_element;
else
return m_zero_index_adress[index];
}
private:
int m_min_index;
int m_size;
T* m_base_address;
T* m_zero_index_adress;
T m_default_element;
};
This seems unneccessarily complicated to me. I really don't see why the developer didn't chose to implement element access via m_base_address[index+m_min_index]. But worse, I am worried that this current implementation could be dangerous. The code seems to work reliably but I was wondering what would happen if there is an arithmetic overflow in the calculation of m_zero_index_address, i.e. if the minimum index offset is greater than the allocatead address. Is there a chance for this to go horribly wrong or is this code always safe?
Upvotes: 0
Views: 83
Reputation: 385405
Your instinct is correct.
It is undefined to form that pointer so far out of the bounds of the array, overflow is a very real issue, and the author should have done precisely what you suggest.
[C++11: 5.7/5]:
When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integral expression. [..] If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.
Upvotes: 7