Это не безопасно. Причина проста:
Любая переменная в функции будет размещена в стеке, чья память освобождается после возврата из функции. Тот факт, что память освобождена, не означает, что ее содержимое изменилось.
Это означает, что содержимое памяти, которое вы поместили в переменную char buff[20]
, все еще находится в позиции памяти buff
или ptr
(начиная с ptr=buff
). Всякий раз, когда вы вызываете другую функцию (или выполняете другой блок), ее переменные функции / блока также попадают в стек, создавая возможность изменения содержимого памяти, для которого указана позиция ptr
.
В примере strcpy
, который вы написали, вам повезло, что переменные функции strcpy не попали в стек в положении, которое было внутри старого массива buff
. Вот почему у вас сложилось впечатление, что это было безопасно.
Вывод таков: вы не можете гарантировать, что содержимое освобожденной памяти стека не изменится между двумя вызовами функций.
Решение состоит в том, чтобы использовать malloc
, поскольку malloc
выделяет память не в стеке, а в куче. Память кучи не освобождается, если вы не решили сделать это (по бесплатному вызову).
Этот подход гарантирует, что память, указанная ptr
, безопасна для использования любой другой функцией.
Недостаток этого решения является внутренним: как только память не освобождается, если вы не делаете это программно, если вы забудете освободить эту память и потерять содержимое ptr
, эта память будет выделена для вашей программы, но никогда не достижимо, потеряно до тех пор, пока ваша программа работает. Эта память станет утечкой памяти: -)
Это одна из причин, почему на некоторых языках есть сборщики мусора ... но это другая история: -)
PS .: Я думаю, что это безопасно (если ваша программа однопоточная), хотя я не рекомендую делать что-то подобное:
{
char safe_buffer[20];
char *unsafe_ptr;
int i;
unsafe_ptr = f1();
/*Copy the buffer without calling any function
not to change the stack content
*/
for(i=0;i<20 && *(unsafe_ptr + i) != 0;i++)
{
*(safe_buffer + i) = *(unsafe_ptr + i);
}
*(safe_buffer + i) = 0;
f2(safe_buffer);
}