Добрый день.Подскажите, пожалуйста, почему данная функция при переодическом выполнении вызывает рост программы в памяти и каким образом это можно исправить.
/////////////////////////////////////////////////////////////////
long getRuleCount(const char *id)
{
static int s = -1; /* the socket */struct ip_fw *r;
#define NEXT(r) ((struct ip_fw *)((char *)r + RULESIZE(r)))
int seen = 0, nbytes;
long bytes = 0;
u_long rnum;
char rule[7];int nalloc = 1024; /* start somewhere... */
/* get rules or pipes from kernel, resizing array as necessary */
nbytes = nalloc;if (s == -1)
s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (s < 0)
send_error("socket error(IPFW)");r = NULL;
while (nbytes >= nalloc)
{
nalloc = nalloc * 2 + 200;
nbytes = nalloc;if ((r = (ip_fw*)realloc(r, nbytes)) == NULL)
{ }sprintf(rule, "%s%s", (IPFW_PREFIX), id);
rnum = atoi(rule);for (int n = seen = 0; n < 65535, r->rulenum <= rnum; n++, r = NEXT(r))
{
if (r->rulenum == rnum)
{
bytes += (long)r->bcnt;
seen = 1;
}
}if (!seen)
{
char err[50];
sprintf(err, "Rule %lu does not exist", rnum);
send_error(err);return -1;
}#undef NEXT
return bytes;
}
send_error("Error on realloc (IPFW)");return -1;
}/////////////////////////////////////////////////////////////////
>Добрый день.
>
>Подскажите, пожалуйста, почему данная функция при переодическом выполнении вызывает рост программы в
>памяти и каким образом это можно исправить.
>
>/////////////////////////////////////////////////////////////////
>long getRuleCount(const char *id)
>{
> static int s = -1;
> /* the socket */
>
> struct ip_fw *r;
>
>#define NEXT(r) ((struct ip_fw *)((char *)r + RULESIZE(r)))
>
> int seen = 0, nbytes;
> long bytes = 0;
> u_long rnum;
> char rule[7];
>
> int nalloc = 1024; /* start somewhere...
>*/
>
>
> /* get rules or pipes from kernel, resizing array
>as necessary */
> nbytes = nalloc;
>
> if (s == -1)
> s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
> if (s < 0)
> send_error("socket error(IPFW)");
>
> r = NULL;
Тут мы проинициализировали указатель нулевым значением ...>
> while (nbytes >= nalloc)
> {
> nalloc = nalloc * 2 +
>200;
> nbytes = nalloc;
>
> if ((r = (ip_fw*)realloc(r, nbytes)) ==
>NULL)
> { }
>
Тут конечно все грязно, без обработки ошибок, но .. Тут ты выделяешь динамическую память, если указатель будет нулевым, или перевыделяешь память, если указатель ен нулевой ... Как результат - выделенная динамическая память ...> sprintf(rule, "%s%s", (IPFW_PREFIX), id);
> rnum = atoi(rule);
>
> for (int n = seen = 0; n < 65535, r->rulenum <= rnum; n++, r = NEXT(r))
> {
> if (r->rulenum == rnum)
> {
> bytes += (long)r->bcnt;
> seen = 1;
>
> }
> }
>
> if (!seen)
> {
> char err[50];
> sprintf(err, "Rule %lu does not exist",
>rnum);
> send_error(err);
>
> return -1;
> }
>
>
>
>#undef NEXT
>
>
> return bytes;
>}
> send_error("Error on realloc
>(IPFW)");
>
> return -1;
> }
>
>/////////////////////////////////////////////////////////////////
Которую ты нигде не освободил.Итак, при многократном выполнеини твоей программы выделается все больше и больше динамической памяти...
Исправляй, man free. Творческих тебе узбеков :)
Пробовал free(r):
a.out in free(): error: pointer to wrong page
Abort trap (core dumped)
я ведь смещаю указатель в цыкле и оно, видимо не знает чего высвобождать, пробовал не смещать (неработоспособный вариант) всё-равно память растёт... :(
исправляюсь: если не смещать указатель - память дружелюбно высвобождается и роста нет, как мне её высвободить в этом случае???
>исправляюсь: если не смещать указатель - память дружелюбно высвобождается и роста нет,
>как мне её высвободить в этом случае???Конечно освобождения "левого" указателя ничего не даст. Перед тем, как смешать r, сохрани его копию. Например:
void *copy_of_r = (void *)r;
И перед возвратом управления:
free(copy_of_r);
....
удачи.
Всё спасибо, разобрался: перед цыклом, где был перебор правил надо было обьявить новый указатель, типа: struct ip_fw *rul = r;
>Всё спасибо, разобрался: перед цыклом, где был перебор правил надо было обьявить
>новый указатель, типа: struct ip_fw *rul = r;
Вообще загляни в ipfw.c ... Там есть прекрасный пример перебора правил брандмауэра)))
>>Всё спасибо, разобрался: перед цыклом, где был перебор правил надо было обьявить
>>новый указатель, типа: struct ip_fw *rul = r;
>
>
>Вообще загляни в ipfw.c ... Там есть прекрасный пример перебора правил брандмауэра)))
>
я оттуда и взял ;)