char * buf = (char*) malloc (PWD_BUF_SIZE * sizeof (char)); buf = getcwd (buf, PWD_BUF_SIZE); ... free(buf); Удалили память, потому что выделили. char * buf = getcwd(NULL, PWD_BUF_SIZE); ... free(buf) Удалили память, но на этот раз мы не выделяли. char f[] = "/home/user/1.txt"; char * b = basename(f); ... free(b); // привело к ошибке. Почему последний вариант привел к ошибке? Чтобы лучше понять, нужно реализовать функцию basename. Как? Если представим, что внутри ее выделяется память через alloca, то внутри функции она должна была бы освободится. То есть я хочу понять, когда освобождать память, и научится создавать функции такого типа как basename, которые возвращают указатель на память, которую не нужно удалять. С первыми двумя примерами все понятно. Если мы передает NULL, то память выделяется автоматически размером PWD_BUF_SIZE.
Ответ
@andrey1, освобождать (free()) можно только ту память, которая получена в результате malloc()/calloc()/realloc() (или функций, которые возвращают результат вызова malloc/calloc/realloc).
Обратите внимание, в free нельзя передавать адрес откуда-то из середины выделенного блока (только начальный адрес) и нельзя передавать его более одного раза.
Конечно, я говорю о стандартной (общепринятой) их реализации. В принципе же вполне можно представить аллокатор, хранящий адреса и размеры всех выделенных блоков, (например в rb-tree), который позволяет удалять "хвосты" (и даже расщеплять ранее выделенный блок) и безболезненно реагирует на realloc/free по неправильным адресам. Расплатой за возможность таких "вольностей" будет потеря эффективности.
По поводу dirname() и basename().
Думаю, тривиальный примерчик (с печатью адресов) все ставит на свои места:
#include
int
main (int ac, char *av[])
{
char *s = "/usr/lib/", *p = strdup(s),
*d = dirname(p), *b = basename(p);
printf ("s = %p\t[%s]
"
"p = %p\t[%s]
"
"d = %p\t[%s]
"
"b = %p\t[%s]
",
s, s, p, p, d, d, b, b);
char *q = strdup(s), *n = basename(q);
printf ("q = %p\t[%s]
"
"n = %p\t[%s]
",
q, q, n, n);
free(p); // or free(d);
free(q);
return 0;
}
Результат запуска:
avp@avp-ubu1:hashcode$ gcc c.c
avp@avp-ubu1:hashcode$ ./a.out
s = 0x4007d8 [/usr/lib/]
p = 0x242b010 [/usr]
d = 0x242b010 [/usr]
b = 0x242b011 [usr]
q = 0x242b030 [/usr/lib]
n = 0x242b035 [lib]
avp@avp-ubu1:hashcode$
Тут становится очевидно, что
uname -a
Linux avp-ubu1 3.13.0-34-generic #60-Ubuntu SMP Wed Aug 13 15:45:27 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
эти функции меняют переданный аргумент (ставят нули) "по месту" (никакого копирования).
Комментариев нет:
Отправить комментарий