реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Вопрос по LwIP, netconn_recv возвращает ERR_MEM
l_fin_l
сообщение Dec 28 2016, 05:19
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 28
Регистрация: 23-08-11
Пользователь №: 66 836



Здравствуйте, использую LwIP порт для stm32f207(компилятор IAR), при работе более 24 часов, функция netconn_recv возвращает ошибку ERR_MEM. Не могу понять где не хватает памяти, как я понял стек выделяет для приема память из PBUF_POOL. Возможно я что-то недопонимаю, заранее спасибо.
Go to the top of the page
 
+Quote Post
scifi
сообщение Dec 28 2016, 08:29
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 711
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(l_fin_l @ Dec 28 2016, 08:19) *
Не могу понять где не хватает памяти

Для таких случаев там есть возможность сбора статистики. Включите её и посмотрите, что там кончилось.
Go to the top of the page
 
+Quote Post
l_fin_l
сообщение Dec 28 2016, 11:06
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 28
Регистрация: 23-08-11
Пользователь №: 66 836



lwip_stats выдает в поле "NETBUF" следущее:
-avail:6
-used:2
-max:3
-err:1
-illegal:0
т.е. как я понимаю, он не смог выделить память под структуру netbuf, хотя разрешенное мной кол-во составляет 6, а откуда он черпает память для выделения под структуры этого типа?
Go to the top of the page
 
+Quote Post
scifi
сообщение Dec 28 2016, 11:11
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 711
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(l_fin_l @ Dec 28 2016, 14:06) *
т.е. как я понимаю, он не смог выделить память под структуру netbuf

Интересно, откуда это следует?
Правильнее будет сохранять всю статистику каждый час. Потом можно посмотреть, что утекает со временем.
Go to the top of the page
 
+Quote Post
l_fin_l
сообщение Dec 28 2016, 11:21
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 28
Регистрация: 23-08-11
Пользователь №: 66 836



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

С другими типами структур все в порядке, всего хватает.
Go to the top of the page
 
+Quote Post
Pridnya
сообщение Dec 29 2016, 05:25
Сообщение #6


Частый гость
**

Группа: Свой
Сообщений: 139
Регистрация: 11-01-11
Из: Орел
Пользователь №: 62 159



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

Укажите хотя бы версию LwIP, а то люди отвечают даже не зная какая у вас версия (1.3.2...2.0.0). rolleyes.gif
И версию компилятора тоже можно указать.
Go to the top of the page
 
+Quote Post
l_fin_l
сообщение Dec 29 2016, 08:00
Сообщение #7


Участник
*

Группа: Участник
Сообщений: 28
Регистрация: 23-08-11
Пользователь №: 66 836



LwIP 1.4.0, IAR - 7.80.2
Go to the top of the page
 
+Quote Post
scifi
сообщение Dec 29 2016, 08:43
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 711
Регистрация: 7-02-07
Пользователь №: 25 136



Кстати, ERR_MEM не обязательно означает, что кончилась память. Если заглянуть в исходники lwip, в некоторых ситуациях этот код возвращается не из-за исчерпания памяти, а из-за достижения других ограничений.
В общем, хорошо бы поймать в отладчике момент, когда возникает этот код, и установить точную причину.
Кстати, неплохо было бы включить вывод диагностической информации. Там точно будет сообщение о причине ERR_MEM.
Go to the top of the page
 
+Quote Post
l_fin_l
сообщение Dec 29 2016, 09:08
Сообщение #9


Участник
*

Группа: Участник
Сообщений: 28
Регистрация: 23-08-11
Пользователь №: 66 836



Ошибка вылетает в функции 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]
  }

Go to the top of the page
 
+Quote Post
Pridnya
сообщение Dec 29 2016, 09:09
Сообщение #10


Частый гость
**

Группа: Свой
Сообщений: 139
Регистрация: 11-01-11
Из: Орел
Пользователь №: 62 159



Цитата(scifi @ Dec 29 2016, 11:43) *
Кстати, неплохо было бы включить вывод диагностической информации. Там точно будет сообщение о причине ERR_MEM.

Для этого нужно настроить какой-нибудь UART на вывод, переопределить макрос, который выводит отладочные строки в конкретный UART, и в настройках стека разрешить вывод отладочной информации вообще и в конкретных ситуациях.
Go to the top of the page
 
+Quote Post
l_fin_l
сообщение Dec 29 2016, 13:53
Сообщение #11


Участник
*

Группа: Участник
Сообщений: 28
Регистрация: 23-08-11
Пользователь №: 66 836



Цитата
Для этого нужно настроить какой-нибудь 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 - Dec 29 2016, 13:54
Go to the top of the page
 
+Quote Post
l_fin_l
сообщение Jan 5 2017, 12:23
Сообщение #12


Участник
*

Группа: Участник
Сообщений: 28
Регистрация: 23-08-11
Пользователь №: 66 836



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

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



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

Сообщение отредактировал l_fin_l - Jan 5 2017, 12:25
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 5 2017, 13:36
Сообщение #13


Гуру
******

Группа: Модераторы
Сообщений: 7 985
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



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


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
l_fin_l
сообщение Jan 5 2017, 14:55
Сообщение #14


Участник
*

Группа: Участник
Сообщений: 28
Регистрация: 23-08-11
Пользователь №: 66 836



Я понимаю, что это маркер конца списка, просто сам список состоит далеко не из шести элементов. Хотя на этапе инициализации создается список из шести элементов. Или он изменяется в процессе работы?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 5 2017, 16:21
Сообщение #15


Гуру
******

Группа: Модераторы
Сообщений: 7 985
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



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


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 17th August 2017 - 17:32
Рейтинг@Mail.ru


Страница сгенерированна за 0.24237 секунд с 7
ELECTRONIX ©2004-2016