Доступ к массиву с отрицательным числом!

Я преобразовываю большую и очень старую (более 25 лет!) программу чрезвычайно с C на С++.

В нем много (очень много) мест, где я обращаюсь к глобальному одномерному массиву UBYTE, используя множество целочисленных индексов. Иногда этот индекс может быть отрицательным.

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

Но теперь в С++ кажется, что обращение к массиву с отрицательным числом ведет себя по-другому, и теперь у меня плохо работает программа. Я зафиксировал один случай необработанного отрицательного числа, и программа, похоже, работает нормально, но я нервничаю, что не попал в ловушку всех отрицательных чисел, и могут быть проблемы впереди.

Итак, теперь мой вопрос: есть ли способ во время выполнения обнаружить все экземпляры доступа к массивам с отрицательными индексами? Я буду впечатлен, если кто-нибудь сможет ответить. Если вы совершенно уверены, что это невозможно сделать автоматическим способом, то я также скажу, что это тоже ценная информация.

Я должен просто добавить, что я на самом деле не программист на С++ (пока). Пока все, что я сделал, - это абсолютный минимум (почти ничего), чтобы программа могла скомпилироваться под компилятором С++. Поэтому, если ваш ответ включает в себя фантастические "только эксперты, решения на С++", попробуйте объяснить словами одного слога или дать мне ссылку, чтобы я мог ее найти.

Ответы

Ответ 1

Можно ли заменить глобальный одномерный массив ubyte объектом с перегруженным оператором []? Использование абсолютного значения ввода int может решить некоторые из ваших проблем.

Изменить: в зависимости от шаблона использования вашего массива (без указателя shenanigans) использование объекта с перегруженным оператором [] может быть полностью прозрачным для пользователей массива, поэтому мое предложение.

Ответ 2

Знаете ли вы границы индексов?

Считая комментарий в ответ Siyfion, кажется, что отрицательные индексы разрешены в вашей проблемной области, и поэтому нет смысла пытаться заставить все индексы быть положительными. Лучшее решение - разрешить отрицательные индексы, не нарушая каких-либо языковых правил (к которым также добавила ваша версия C. Вам просто повезло, что она не взорвалась;))

Итак, если вы знаете, что индексы, которые вы собираетесь использовать, находятся в диапазоне от -x до y, просто создайте массив размером x + y и используйте указатель на x-й элемент при доступе к массиву.

Например, если вам нужен массив с индексами от -4 до 5:

int arr[10];
int* ptr = arr+4;
// use ptr when you need to index into the array:

ptr[-4]; // is valid, reads arr[0]
ptr[5]; // is valid, reads arr[9]

Конечно, то же самое могло (и должно) было сделано на C.

Другим советом было бы не напрямую обращаться к необработанному массиву. Вместо этого определите простые функции доступа. (например, но не обязательно, поместив массив в класс.Если вы поместите его в класс, вы можете перегрузить operator [], чтобы он даже выглядел как массив)

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

Ответ 3

Может работать какой-то способ использования памяти, особенно если вы можете заставить массив перейти на свою собственную страницу. Я бы использовал valgrind в Linux, не уверен, что вы будете использовать в Windows - purify?

Ответ 4

Оберните его. В альтернативном случае проверьте, поддерживает ли ваш компилятор проверку границ. В худшем случае я не ставил бы допустимые значения в вашем массиве на отрицательные числа. Я бы поставил откровенно неправильные значения, так что вы получите явно неправильное значение, когда это произойдет. Вы не будете определять проблему без отладчика, но, по крайней мере, у вас есть четкое предупреждение о том, что где-то это делает какой-то код.

Ответ 5

Есть ли способ, во время выполнения, для меня для обнаружения любых случаев доступа массивы с отрицательными индексами?

Замените свой глобальный массив std::vector. Замените использование синтаксиса array[index] на

vector.at(index)

Это делает именно то, о чем вы просите: он добавляет проверки привязки массива времени выполнения.

Ответ 6

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

Ответ 7

Лично я попытаюсь разобраться, почему любой из ваших индексов может когда-либо быть отрицательным; очевидно, что они вернут неправильное значение, поэтому, конечно, вы не должны позволить индексу идти отрицательно?

Исправьте код, который позволяет им идти отрицательно, а не пытаться превратить квадратный штекер в круглое отверстие (так сказать);)

Ответ 8

Одна вещь, которую вы можете сделать, - это проверить, до какой минимальной ценности ваши индексы идут, и начать заполнять свой массив из этого индекса.

a [-i] = * (a - i)

начните с (a-i) в качестве базового адреса вместо (a), чтобы вы просто сдвинули массив и получили желаемые значения.