struct foo
{
int a;
int b;
};
void* p = (void*)malloc(sizeof(struct foo));
((foo*)p)->a;//do something.
free(p);//Is this safe?
Можно ли освободить 'void *'?
Ответ 1
Да.
malloc возвращает void *
, а free принимает void *
, поэтому некоторые ваши приведения бессмысленны, и вы всегда освобождаете void *
, даже если вы начинаете с какого-то другого указателя.
Ответ 2
Да, это безопасно. При распределении памяти библиотека времени выполнения отслеживает размер каждого распределения. Когда вы вызываете free(), он просматривает адрес, и если он находит выделение для этого адреса, освобождается правильный объем памяти (блок, который был выделен по этому адресу).
Ответ 3
Да - free
принимает указатель на void, поэтому, когда вы его вызываете, указатель (неявно) отбрасывается на указатель на пустоту в любом случае.
Остальная часть вашего кода не совсем безопасна:
void* p = (void*)malloc(sizeof(foo));
Вы не должны отбрасывать возврат из malloc (в C). Это может скрыть ошибку, забыв о #include <stdlib.h>
Ответ 4
Да. Прототип функции для free
равен:
void free(void *ptr);
Ответ 5
в C это совершенно безопасно, потому что нет деструкторов для вызова.
система памяти отслеживает размер распределения.
в С++ вы должны удалить тот же тип, что и новый, в том числе с помощью оператора delete [] для удаления новых массивов.
это только для того, чтобы вызывать деструкторы.
Ответ 6
Возможно, он не чувствует себя в безопасности из-за того, что магия происходит за кулисами. Среда выполнения C и/или сама ОС активно отслеживают память, возвращаемую malloc, включая ее размер и местоположение. Смотрите, хотя кажется, что вы передаете беззнаковый указатель обратно в free(), вы фактически передаете ссылку на объект, который активно отслеживает менеджер памяти.
Ответ 7
да, это безопасно.
Ответ 8
Да, но обычно это признак плохого дизайна. malloc() обычно используется для выделения буферов (больших массивов одного и того же примитивного типа) или объектов (структуры с инициализированными полями). В обоих случаях malloc и free должны соответствовать таким образом
unsigned char *rgba_buffer = malloc(width * hieght * 4);
/* use the buffer here */
free(rgba_buffer);
BITSTREAM *bs = bitstream("bitfile.boin");
/* use the bitstream here */
destroy_bitstream(bs);
typedef struct
{
FILE *fp;
unsigned char ch;
int index;
} BITSTREAM;
BITSTREAM *bitstream(const char *filename)
{
BITSTREAM *bs = malloc(sizeof(BITSTREAM));
bs->fp = fopen(filename "rb");
/* etc */
return bs;
}
void destroybitstream(BITSTREAM *bs)
{
if(bs)
{
if(bs->fp)
fclose(bs->fp);
free(bs);
}
}
В одном случае malloc и свободное совпадение, в другом возвращается выделенная память, есть также вторичные ресурсы, а конструктор и деструктор совпадают. Нужно редко выделять область памяти, но не знать, для чего она используется. И вы не должны чередовать распределения и освобождать хаотично.
Современный С++ ужесточает все это с помощью уникальных указателей, которые "владеют" объектом. Хотя вы можете иметь уникальный указатель на пустоту, это было бы очень редко.