Проблема в основном исторический артефакт, а не невозможность реализации.
Большинство компиляторов Си создают код так, что компилятор видит только каждый исходный файл одновременно; он никогда не видит всю программу сразу. Когда один исходный файл вызывает функцию из другого исходного файла или библиотеки, все, что видит компилятор, - это файл заголовка с типом возвращаемого значения функции, а не фактическим кодом функции. Это означает, что когда есть функция, которая возвращает указатель, компилятор не может сказать, нужно ли освобождать память, на которую указывает указатель, или нет. Информация для принятия решения, которая не отображается компилятору в этот момент времени. С другой стороны, человек-программист может свободно искать исходный код функции или документацию, чтобы выяснить, что нужно сделать с указателем.
Если вы посмотрите на более современные низкоуровневые языки, такие как C ++ 11 или Rust, вы обнаружите, что они в основном решили проблему, сделав явное владение памятью в типе указателя. В C ++ вы должны использовать unique_ptr<T>
вместо обычного T*
для хранения памяти, и он unique_ptr<T>
гарантирует, что память освобождается, когда объект достигает конца области, в отличие от простого T*
. Программист может передавать память от одного unique_ptr<T>
к другому, но может быть только один, unique_ptr<T>
указывающий на память. Так что всегда понятно, кому принадлежит память и когда ее нужно освободить.
C ++ по причинам обратной совместимости все еще допускает ручное управление памятью старого стиля и, таким образом, создание ошибок или способов обойти защиту unique_ptr<T>
. Rust еще более строг в том смысле, что он обеспечивает соблюдение правил владения памятью через ошибки компилятора.
Что касается неразрешимости, проблемы остановки и тому подобного, да, если вы придерживаетесь семантики C, для всех программ невозможно решить, когда освободить память. Однако для большинства актуальных программ, а не для академических упражнений или программного обеспечения с ошибками, абсолютно возможно решить, когда освободить, а когда нет. В конце концов, это единственная причина, по которой человек может понять, освободить его или нет.