free () в памяти стека - PullRequest
       25

free () в памяти стека

8 голосов
/ 22 апреля 2010

Я поддерживаю некоторый код c на Solaris, и я видел что-то странное, по крайней мере, я думаю, что это:

char new_login[64];
...
strcpy(new_login, (char *)login);
...
free(new_login);

Насколько я понимаю, поскольку переменная является локальным массивом, память поступает из стека и не нуждается в освобождении, и, кроме того, поскольку не используется malloc / calloc / realloc, поведение не определено.

Это система реального времени, поэтому я думаю, что это пустая трата циклов. Я что-то упускаю из виду?

Ответы [ 6 ]

17 голосов
/ 22 апреля 2010

Вы можете освободить только то, что получили из функций malloc (), calloc () или realloc (). освобождение чего-либо в стеке приводит к неопределенному поведению, вам повезло, что это не приведет к сбою вашей программы или, что еще хуже.

Считайте, что это серьезная ошибка, и удалите эту строку как можно скорее.

7 голосов
/ 22 апреля 2010

Нет. Это ошибка.

По свободному (3) ....

free () освобождает указанную область памяти к ptr, который должен был возвращено предыдущим звонком malloc (), calloc () или realloc (). В противном случае, или если свободный (ptr) уже был вызван ранее, неопределенный поведение происходит. Если ptr равен NULL, нет операция выполнена.

Итак, в вашей программе происходит неопределенное поведение.

3 голосов
/ 23 апреля 2010

Функция free () определенно является ошибкой.
Однако, возможно, здесь есть еще одна ошибка:


   strcpy(new_login, (char *)login);

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

   new_login[sizeof(new_login)-1]='\0';
   strncpy(new_login, (char *)login, sizeof(new_login)-1 );
3 голосов
/ 22 апреля 2010

Определенно ошибка. free() ДОЛЖЕН использоваться ТОЛЬКО для выделенной памяти кучи, если только она не переопределена для выполнения чего-то совершенно другого, что я сомневаюсь в этом.

2 голосов
/ 23 апреля 2010

В БОЛЬШИХ СЛУЧАЯХ вы можете только освободить () что-то, выделенное в куче. См http://www.opengroup.org/onlinepubs/009695399/functions/free.html.

ОДНАКО: Один из способов сделать то, что вы хотели бы сделать, - это scope временных переменных, размещенных в стеке. примерно так:

{
char new_login[64];
... /* No later-used variables should be allocated on the stack here */
strcpy(new_login, (char *)login);
}
...
1 голос
/ 23 апреля 2010

Спасибо. Рад видеть, что я не сумасшедший. Кроме того, не было проверки границ на strcpy. Я обычно использую strncpy, чтобы избежать подобных вещей.

...