2014-01-03 3 views
0

Недавно я встретил класс C++, который реализует ненулевой индексный массив. То есть можно было бы инициализировать этот класс, чтобы иметь допустимый диапазон индексов, например, 15..19. Этот класс вычисляет адрес для элемента с индексом 0, хотя он, вероятно, находится за пределами выделенного адресного пространства и сохраняет этот адрес. Доступ к элементу затем обрабатывается только с помощью оператора [], используя этот адрес элемента 0. Некоторый примерный код (упрощенный):Оператор массива, использующий адрес за пределами массива

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; 
}; 

Это кажется мне нелегко сложным. Я действительно не понимаю, почему разработчик не решил реализовать доступ к элементу через m_base_address [index + m_min_index]. Но что еще хуже, я обеспокоен тем, что нынешняя реализация может быть опасной. Код, похоже, работает надежно, но мне было интересно, что произойдет, если в вычислении m_zero_index_address произойдет арифметическое переполнение, т. Е. Если минимальное смещение индекса больше адреса allocatead. Есть ли шанс для этого пойти ужасно неправильно или этот код всегда безопасен?

+1

Забавный факт: он использует 'malloc' :-) –

ответ

7

Ваш инстинкт верен.

Невозможно сформировать этот указатель так далеко от границ массива, переполнение является очень реальной проблемой, и автор должен был сделать именно то, что вы предлагаете.

[C++11: 5.7/5]: Когда выражение, которое имеет целочисленный тип добавляется или вычитается из указателя, результат имеет тип указателя операнда. Если операнд указателя указывает на элемент объекта массива, и массив достаточно велик, результат указывает на смещение элемента от исходного элемента, так что разность индексов результирующих и исходных элементов массива равна интегральному выражению. [..] Если оба операнда указателя и результат указывают на элементы одного и того же объекта массива или один за последним элементом объекта массива, оценка не должна приводить к переполнению; иначе поведение не определено.

Смежные вопросы