Возможное решение проблемы ссылок в языках программирования

xl4duyyseltgpsqlhu09_vp-zvk.jpeg

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

К сожалению ссылки, точнее ручное управление памятью, является наиболее частой причиной возникновения различных ошибок и уязвимостей в программном обеспечении. А все попытки автоматического управления памятью с помощью различных менеджеров упираются в необходимость контролировать создание и удаление объектов, а так же периодически запускать сборщик мусора, что отнюдь не положительно сказывается на производительности приложений.

Тем не менее, ссылки в той или иной форме поддерживаются во всех языках программирования, хотя под этим термином часто подразумеваются не полностью эквивалентные термины. Например, под словом «ссылка» можно понимать ссылку как адрес в памяти (как в С++) и ссылку, как указатель на объект (как в Python или Java).

Хотя встречаются языки программирования, которые пытаются решать данные проблемы за счет концепции «владения» (Rust, Аргентум или NewLang). О возможном решении этих, и других имеющихся проблем со ссылками далее и пойдет речь.


Какие ссылки бывают?

Например, в языке C есть указатели, но работать с ними не очень удобно и одновременно очень опасно из-за наличия адресной арифметики (возможности напрямую изменять адрес указателя на данные в памяти компьютера). В C++ появилась отдельная сущность — reference, а в C++11 ссылки получили дальнейшее развитие, появились rvalue-ссылки.

Тогда как в С++ существует сразу несколько видов ссылок, то разработчики Python наверно специально попробовали «упростить» работу со ссылками и вообще отказались от них. Хотя де факто в Python каждый объект является ссылкой, хотя некоторые типы (простые значения) автоматически передаются по значению, тогда как сложные типы (объекты) всегда по ссылке.


Циклические ссылки

Еще существует глобальная проблема циклический (круговых) ссылок, которая затрагивает практически все языки программирования (когда объект прямо или через несколько других объектов указывать на самого себя). Часто разработчикам языка (в первую языков со сборщикам муроса) приходится идти на различные алгоритмические ухищрения, чтобы почистить пул созданных объектов от подобных «зависших» и циклических ссылок, хотя обычно эту проблему отдают на откуп разработчикам, например, в С++ есть сильные (std: shared_ptr) и слабые (std: weak_ptr) указатели.


Неоднозначная семантика ссылок

Еще не менее важной, но часто игнорируемой проблемой ссылок является семантика языка для работы с ними. Например в С/С++ для обращения к данным по ссылке и по значению используются отдельные операторы звездочка »*», стрелочка »» и точка ».». Но работа с reference переменными в С++ происходит как с обычными переменными «по значению», хотя по факту это не так. Конечно при явной типизации С++, компилятор не даст ошибиться, но при обычном чтении кода, у вас не получится отличить reference переменную от обычной «по значению».

А вот в Python можно очень легко попутать как будет происходить передача переменой в качестве аргумента функции, по значению или по ссылке. Так как это зависит от самих данных, которые содержатся в переменной. Особой пикантности тут добавляет тот факт, что Python является языком программирования с динамической неявной типизацией, и в общем случае заранее не известно, какое значение хранится в переменной.


Кто виноват и что делать?

Мне кажется, что основная причина, по крайней мере неоднозначной семантики, это постоянный рост сложности инструментов разработки, и как следствие — усложнение и доработка синтаксиса языков программирования под новые концепции и возможности с сохранением обратной совместимости со старым legacy кодом.

А что если начать с чистого листа? Вот например, универсальная концепция управления объектами и ссылками на объекты, которая не требует от пользователя (программиста) ручного управления памятью, для которой не нужен сборщик мусора, а ошибки при работе с памятью и ссылками на объекты становятся невозможны за счет полного контроля управления памятью еще на этапе компиляции исходного кода приложения!


Термины:

Объект — данные в памяти компьютера в машинном (двоичном) представлении.
Переменная — человекочитаемый идентификатор в теле программы, который однозначно определяется по своему имени и идентифицирует объект (непосредственное значение объекта или ссылку на него). Переменные могут быть:


  • Переменная владелец — единственная постоянная ссылка на объект (shared_ptr).
  • Переменная ссылка — временная ссылка на объект (weak_ptr).


Возможные операции:


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

Пример исходного кода и условные сокращения:


  • »&» — создание ссылки на переменную
  • »*» — обращение к данным объекта
# переменные - владелец
val1 := 1; 
val2 := 2;
# val1 = 1, а val2 = 2

val1 = val2; # Ошибка - владелец только один!
*val1 = *val2; # ОК - присваивается значение
# val1 = 2, а val2 = 2

# переменные - ссылки
ref1 := &val1;
ref2 := &val2;
# ref1 -> val1, а ref2 -> val2

ref1 = 3; # Ошибка - переменная является ссылкой!
*ref1 = 3; # ОК - значение присваивается "по ссылке"
# val1 = 3, а val2 = 2

*ref2 = *ref1;  # ОК - одно значение присваивается другому значению "по ссылке"
# val1 = 3, а val2 = 3

ref1 = ref2; # ОК - одна ссылка присваивается другой ссылке
# ref1 -> val2, а ref2 -> val2

ref1 = 5;
# val1 = 5, а val2 = 5

При таком синтаксисе все становится просто, наглядно и понятно. Но если я что-то где-то упустил, напишите пожалуйста в комментарии или в личном сообщении.

© Habrahabr.ru