среда, 24 февраля 2021 г.

Обнаружил дичайшую вещь

Мы разбирали этот пример на курсах программирования, но я не придал этому особого значения тогда. А теперь вот вспомнил.

Сделал выборку элементов из массива с помощью массива в качестве индекса для функции get класса [] (ValueArray).

Выборка элементов массива с помощью массива как индекса

Так вот, дичайшая вещь состоит в том, что в данных массива типа ValueArray я храню указатели на объекты типа StackValue. И всё бы прекрасно, но чтобы не возиться с подсчётом ссылок, при изменении размеров фрейма стека я просто копирую эти значения, и таким образом, если внутри функции я вызываю другую функцию, которая изменяет стек, то старые указатели уже не работают. Поэтому я не могу использовать переменные-ссылки при работе с массивом типа ValueArray.

А дичь вот в чём. 

У меня возникла непонятная ошибка. Я ведь получаю текущие значения указателей в массиве. Но ошибка была в моём коде. Он выглядит так:

#define arr (stack->at(ctx->object))

#define idx (stack->at(ctx->param))

#define nval (idx.array_at(n))


result->array_push_back(arr.array_at(nval.get_size(ctx)));


Глядя на эту строку, можно подумать, что компилятор превращает это в код вида:


size_t nn = nval.get_size(ctx);

const StackValue& val = arr.array_at(nn);

result->array_push_back(val);


А на самом деле в код вида:


const StackValue& v1 = arr;

const StackValue& v2 = nval;

size_t nn = v2.get_size(ctx);

const StackValue& val = v1.array_at(nn);

result->array_push_back(val);


Получается дичайшая дичь, потому что функция get_size() изменяет стек. И первый пример кода работает правильно, а второй вызывает ошибку.


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


В данном случае я думаю поступить иначе - буду хранить в данных не указатели, а сами сериализованные объекты. Чтобы при операциях со стеком не терялись указатели. Тогда можно будет использовать переменные-ссылки.

Комментариев нет: