LINUX.ORG.RU

[KERNEL] kfree!!! ошибочка..

 


0

1

Доброе утро!
У меня возникла ошибка при очистке памяти, с помощью функции kfree
Сейчас коротко опишу проблему.
Есть структура: (будем считать что создана структура с именем I_struct и I_struct_ptr указатель на данную структуру)

struct I_struct
{
char *var_1;
char *var_2;
char *var_3;

}


И я выделяю память в ядре, вот так..

I_struct_ptr->var_1 = kmalloc( 4096 ,GFP_ATOMIC); // 4096 Эт просто пример
И такое выделение памяти осуществляется для каждой переменной данной структуры.Кстати говоря, одна из этих переменных может быть равна NULL , что значит, что для неё либо память не выделялась, либо kmalloc вернуло ошибку.

Далее у меня есть некая функция очистки выделенной памяти inline void i_func

inline void i_func(struct I_struct *I_struct_ptr)
{
if(I_struct_ptr == NULL) return;

if(I_struct_ptr->var_1 != NULL ) kfree(I_struct_ptr->var_1);
if(I_struct_ptr->var_2 != NULL ) kfree(I_struct_ptr->var_2);
if(I_struct_ptr->var_3 != NULL ) kfree(I_struct_ptr->var_3);
return; }


После вызова этой функции очистки! вылетает вот такой OOOps

kernel BUG at mm/slub.c:2969!
Apr 6 10:02:50 localhost kernel: invalid opcode: 0000 [#1] SMP
Apr 6 10:02:50 localhost kernel: last sysfs file: /sys/devices/pci0000:00/0000:00:0d.0/host0/target0:0:0/0:0:0:0/block/sda/sda1/uevent

Ошибка происходит при попытке очистить переменную I_struct_ptr->var_2 .

Почему вылетает OOps? как поправить? )

Deleted

Последнее исправление: Deleted (всего исправлений: 1)

>И такое выделение памяти осуществляется для каждой переменной данной структуры

Это точно? Просто указатель мог быть инициализирован мусором, например.

yoghurt ★★★★★
()
Ответ на: комментарий от yoghurt

При каких условиях указатель может быть инициализирован мусором?
Выделение памяти осуществляется скорее всего не для каждой переменной (потому в функции очистки, я и задействовал условия if(var != NULL))
Когда выделяю память для структуры с переменными, то я заполняю её 0-ми. По идее тогда все указатели внутри структуры должны быть равны нулям.

Deleted
()

повторного освобождения точно нет?

if (I_struct_ptr->var_1 != NULL) {
        kfree(I_struct_ptr->var_1);
        I_struct_ptr->var_1 = NULL;
}
arsi ★★★★★
()
Ответ на: комментарий от Deleted

>Когда выделяю память для структуры с переменными, то я заполняю её 0-ми

Тогда ок

yoghurt ★★★★★
()
Ответ на: комментарий от arsi

Спасибо за ответы! дело было в повторной очистке памяти (хотя не ясно, почему выполнялось условие != NULL)
Буду дальше сам внимательней код просматривать.
Ещё раз спасибо за ответы.

Deleted
()
Ответ на: комментарий от Deleted

Потому что kfree не присваивает переменной значение NULL

anonymous
()
Ответ на: комментарий от arsi

kzalloc() же, ну.

Неправильно.


typedef struct A A;
struct A{
 int i;
 void *p;
 /* ... */
 double d;
}
#define zeroA_INI   \
  /* .i = */ 0,     \ 
  /* .p = */ NULL,  \
  /* ... */         \
  /* .d = */ 0.0

/* ... где-то в *.с файле */
static const A g_zeroA = { zeroA_INI };

/* ... где-то в реализации функции ... */
A *pA = kmalloc( sizeof(g_zeroA) ,GFP_ATOMIC);
memcpy(pA, &g_zeroA, sizeof(g_zeroA));

Ибо 0 != NULL || 0.0 != NULL || 0 != 0.0 (т.е. это не гарантируется).

gandjubas
()
Ответ на: комментарий от gandjubas

Перед мемцэпэаем надо на NULL ещё проверить pA конечно же.

gandjubas
()
Ответ на: комментарий от delete83

после предыдущего ответа я начал подозревать, что ты не умеешь читать. теперь я в этом уверен.

arsi ★★★★★
()
Ответ на: комментарий от delete83

> И что же я прочитал не так?

при чём здесь «не так»? сложилось впечатление, что ты вообще не читал тред, ибо несёш полную ахинею, никак не связанную с обсуждаемым вопросом.

arsi ★★★★★
()
Ответ на: комментарий от arsi

Понятно. А то я уж решил, что еще один злостный тролль. Тред то я читал. И ТС уже нашел то, что искал. Просто вы сделали замечание, не совсем верное, вот я и попытался уточнить. В си NULL это все-таки указатель. Хоть и физически равный 0.

delete83 ★★
()
Ответ на: комментарий от arsi

из mm/slab.c:

void kfree(const void *objp)
{
	struct kmem_cache *c;
	unsigned long flags;

	trace_kfree(_RET_IP_, objp);

	if (unlikely(ZERO_OR_NULL_PTR(objp)))
		return;
...

Зачем проверять на то, равен ли var_1 NULL или нет?

DesertFox
()
Ответ на: комментарий от DesertFox

Даже в мане (по free правда) написано, что «Если ptr равен NULL, то ничего не происходит.»

DesertFox
()
Ответ на: комментарий от DesertFox

> Зачем проверять на то, равен ли var_1 NULL или нет?

ТСа спроси ;)

зы: ты изучаешь сорцы всех апи-функций перед их использованием?

arsi ★★★★★
()
Ответ на: комментарий от arsi

Скачал маны по ядру, там тоже самое: «If objp is NULL, no operation is performed».

Так что тут чтения манов достаточно.

А определять поведение своей программы на основе исходников апи-функций это конечно же плохой стиль (история с флэшем это показала). Так что мне надо быть осторожнее))

DesertFox
()
Ответ на: комментарий от DesertFox

привычка же, ну. в том же libc дофига функций, которые не проверяют указатели на NULL, всех не упомнишь... часто проще самому сделать лишнюю проверку перед вызовом, чем каждый раз ман дёргать по этому вопросу...

arsi ★★★★★
()
Ответ на: комментарий от DesertFox

> Зачем проверять на то, равен ли var_1 NULL или нет?

А затем, что время проверки на NULL - стремится к нулю по сравнению со временем вызова функции free/kfree (даже в случае вызова с нул-поинтером в качестве аргумента).

gandjubas
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.