Перейти к содержанию
    

LwIP возвращает ошибку ERR_MEM, STM32F207

Здравствуйте, использую LwIP порт для stm32f207(компилятор IAR), при работе более 24 часов, функция netconn_recv возвращает ошибку ERR_MEM. Не могу понять где не хватает памяти, как я понял стек выделяет для приема память из PBUF_POOL. Возможно я что-то недопонимаю, заранее спасибо.

Изменено пользователем haker_fox
Уточнил название темы, добавил теги, переместил в нужный раздел.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не могу понять где не хватает памяти

Для таких случаев там есть возможность сбора статистики. Включите её и посмотрите, что там кончилось.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

lwip_stats выдает в поле "NETBUF" следущее:

-avail:6

-used:2

-max:3

-err:1

-illegal:0

т.е. как я понимаю, он не смог выделить память под структуру netbuf, хотя разрешенное мной кол-во составляет 6, а откуда он черпает память для выделения под структуры этого типа?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

т.е. как я понимаю, он не смог выделить память под структуру netbuf

Интересно, откуда это следует?

Правильнее будет сохранять всю статистику каждый час. Потом можно посмотреть, что утекает со временем.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Правильнее будет сохранять всю статистику каждый час. Потом можно посмотреть, что утекает со временем.

С другими типами структур все в порядке, всего хватает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Здравствуйте, использую LwIP порт для stm32f207(компилятор IAR), при работе более 24 часов, функция netconn_recv возвращает ошибку ERR_MEM. Не могу понять где не хватает памяти, как я понял стек выделяет для приема память из PBUF_POOL. Возможно я что-то недопонимаю, заранее спасибо.

Укажите хотя бы версию LwIP, а то люди отвечают даже не зная какая у вас версия (1.3.2...2.0.0). :rolleyes:

И версию компилятора тоже можно указать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кстати, ERR_MEM не обязательно означает, что кончилась память. Если заглянуть в исходники lwip, в некоторых ситуациях этот код возвращается не из-за исчерпания памяти, а из-за достижения других ограничений.

В общем, хорошо бы поймать в отладчике момент, когда возникает этот код, и установить точную причину.

Кстати, неплохо было бы включить вывод диагностической информации. Там точно будет сообщение о причине ERR_MEM.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ошибка вылетает в функции netconn_recv, когда пытается выделить память под MEMP_NETBUF(api_lib.c):

  if (conn->type == NETCONN_TCP) {
    struct pbuf *p = NULL;
    /* This is not a listening netconn, since recvmbox is set */

    buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
    if (buf == NULL) {
      NETCONN_SET_SAFE_ERR(conn, ERR_MEM);
      return ERR_MEM;
    }

Ну и в самом маллоке вылетает ошибка(memp.c):

  if (memp != NULL) {
    memp_tab[type] = memp->next;
#if MEMP_OVERFLOW_CHECK
    memp->next = NULL;
    memp->file = file;
    memp->line = line;
#endif /* MEMP_OVERFLOW_CHECK */
    MEMP_STATS_INC_USED(used, type);
    LWIP_ASSERT("memp_malloc: memp properly aligned",
                ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0);
    memp = (struct memp*)(void *)((u8_t*)memp + MEMP_SIZE);
  } else {
[b]    LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", memp_desc[type]));
    MEMP_STATS_INC(err, type);[/b]
  }

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кстати, неплохо было бы включить вывод диагностической информации. Там точно будет сообщение о причине ERR_MEM.

Для этого нужно настроить какой-нибудь UART на вывод, переопределить макрос, который выводит отладочные строки в конкретный UART, и в настройках стека разрешить вывод отладочной информации вообще и в конкретных ситуациях.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для этого нужно настроить какой-нибудь UART на вывод, переопределить макрос, который выводит отладочные строки в конкретный UART, и в настройках стека разрешить вывод отладочной информации вообще и в конкретных ситуациях.

Завтра сделаю, но я все-равно не могу понять что происходит, вроде как место под структуру должно быть, т.к всего 6(используется 2, максимально 3), и он не может выделить память, попадает в:

  } else {
    LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", memp_desc[type]));
    MEMP_STATS_INC(err, type);
  }

Изменено пользователем l_fin_l

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В общем, хорошо бы поймать в отладчике момент, когда возникает этот код, и установить точную причину.

При помощи отладчика увидел проблему, функция memp_malloc при выделении памяти переменной memp(memp_tab[5]) назначает NULL(т.е. не может выделить память)

 

err.png

 

Хотя потом продолжает дальше работать

Изменено пользователем l_fin_l

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

При помощи отладчика увидел проблему, функция memp_malloc при выделении памяти переменной memp(memp_tab[5]) назначает NULL(т.е. не может выделить память)
Это больше похоже на признак конца связанного списка. Отладчику это ничего не говорит и он продолжает честно показывать список дальше - это наблюдающий за отладчиком программист должен понять, что за нулевым указателем искать дальше нечего.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я понимаю, что это маркер конца списка, просто сам список состоит далеко не из шести элементов. Хотя на этапе инициализации создается список из шести элементов. Или он изменяется в процессе работы?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

просто сам список состоит далеко не из шести элементов
Я на вашей картинке вижу, что memp_tab[5] содержит список из трех элементов. При чем тут число шесть, я не понимаю. На указателе, хранящем ноль список заканчивается. Не нужно раскрывать этот элемент - данных по адресу ноль (очередного элемента списка) быть не может (это написано в Стандарте языка Си). Встретили ноль - остановилсь. Список закончился. Дальше данных нет. Указатель "ноль" - это бездна и заглядывать в нее не нужно. По адресу ноль физически располагается начало таблицы векторов прерываний и нет никакого смысла пытаться рассматривать часть ее как элемент списка. Отладчик таких тонкостей не знает и раскроет вам указатель, показывающий куда угодно. Но вы же человек, вы должны думать. Если вы посмотрите исходники, то увидите, что просмотр списка прекращается как только в указателе нашли NULL, а это и есть этот самый ноль.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...