Вижу, что старался, но написано достаточно много, язык тяжёлый и по всему тексту неточности.
" писал(а):указатель еще существует
Нельзя говорить "указатель существует", "удаляем указатель". Это грубейшее нарушение терминологии, которое как раз ведёт к указанным выше непониманиям. Как только мы начнём говорить вместо этого "память существует", "удаляем память", как сразу всё становится на свои места и нужда в подобных громоздких объяснениях тотчас же отпадает.
" писал(а):И даже то, что указатель объявлен внутри функции, ничего не меняят, так как при возврате значения указатель копируется из локальной памяти в глобальную
Тут я даже не знаю что сказать. Не расскажешь мне где эта глобальная память расположена?
На самом деле всё обстоит намного проще. Функция malloc выделяет память в heap'е и возвращает указатель на эту память. Указатель мы записываем в локальную переменную и работаем с ним. В момент выхода из функции мы пишем return и возвращаем указатель. Так, как указатель - это всего лишь переменная, хранящая адрес, то она без каких бы то ни было пробле помещается в регистр EAX, затем функция завершается. После выходы из функции, во внешнюю переменную
cs записывается значение, храняшееся в EAX и мы вновь можем работать с участком памяти, адрес которого только что был возвращён из функции
copy_string. С момента выхода из функции и до вызова
free уже внутри функции
main память, выделенная в heap'е, никак не менялась. Все манипуляции были связаны лишь с передачей
адреса этой памяти. Никакой "глобальной памяти, в которую копируется указатель" нет, не было и не будет.
" писал(а):Ошибка в моём коде - возврат указателя на локальный обект
От того, что ты перенёс вызов
free внутрь функции
copy_string, память, выделенная с помощью
malloc, не станет локальной. И в твоём, и в моём примере, память размещена в heap'e, то есть она динамическая. Ошибка в твоём коде совсем в другом: в возврате указателя на удалённую память, которую наверняка кто-то снаружи захочет прочитать.
" писал(а):а free интересует только содержащийся в указателе адрес, а не сам указатель.
Тотально неверная терминология, либо, как вариант, тотально неверное понимание сути. Если ты внимательно прочитал то мои предыдущие комментарии, то сам должен понять почему это так.
Кстати, вариант с внешним
malloc наоборот более предпочтителен. Есть рекомендация располагать вызовы парных функций (например
malloc и
free) в одном уровне вложенности. Это позволяет легче отлавливать ошибки типа "забыт вызов парной функции". Но это уже другая тема для обсуждения...