首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >LightWeight IP:缓冲区不释放

LightWeight IP:缓冲区不释放
EN

Stack Overflow用户
提问于 2012-06-18 13:28:03
回答 4查看 8.5K关注 0票数 8

我正在使用一个名为lwip的TCP/IP堆栈。我在下面实现了一个函数来发送数据包,这是从接收数据包的类似回调函数中得到的。

每次收到数据包时,我都会使用pbuf_alloc函数创建一个缓冲区。然后,我使用udp_sendto发送数据包。最后,我使用pbuf_free释放缓冲区。(见下面的代码。)

由于某些原因,pbuf_free没有释放缓冲区。(我在n数据包之后会遇到缓冲区溢出,其中n是池大小。) lwip维基警告说:

网络驱动程序也可能不会假设pbuf内存在调用pbuf_free时实际上已被释放。

如何强制pbuf_free释放缓冲区?如何避免缓冲区溢出?

(我的执行情况如下)

代码语言:javascript
复制
static err_t IAP_tftp_send_data_packet(struct udp_pcb *upcb, struct ip_addr *to, int to_port, int block)
{
  err_t err;
  struct pbuf *pkt_buf;
  char packet[TFTP_DATA_PKT_LEN_MAX];
  int bytesRead;
  int bytesToSend;

  /* Specify that we are sending data. */
  IAP_tftp_set_opcode(packet, TFTP_DATA); 

  /* Specify the block number that we are sending. */
  IAP_tftp_set_block(packet, block);

  bytesRead = IAP_tftp_set_data(packet, block);

  if(bytesRead != 0) {
    bytesToSend = TFTP_DATA_PKT_LEN_MAX - (512 - bytesRead + 1);
  } else {
    bytesToSend = TFTP_DATA_PKT_LEN_MAX - 512;
  }

  pkt_buf = pbuf_alloc(PBUF_TRANSPORT, bytesToSend, PBUF_POOL);

  if (!pkt_buf)
  {
    print("(TFTP) Buffer overflow!\r\n");
  }

  /* Copy the file data onto pkt_buf. */
  memcpy(pkt_buf->payload, packet, bytesToSend);

  err = udp_sendto(upcb, pkt_buf, to, to_port);

  /* free the buffer pbuf */
  printf("%d\n\r", pbuf_free(pkt_buf));

  return err;
}
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-07-23 12:10:34

您使用的是什么版本的lwIP?根据不同的版本,答案有很大的不同。

在memp_malloc()中调用的pbuf_alloc()分配函数失败了,或者pbufs链接有failed.So,它返回NULL。

如果传递的参数也包含NULL (由于NULL参数检查),pbuf_alloc()也将返回NULL。

在较新的版本中,能否显示MEMP_OVERFLOW_CHECK宏包含的值?当宏值lwIP 2时,>=显示不同的行为。

另一个原因可能是如果您使用多线程,pbuf_alloc()内部的锁定机制可能会导致它返回NULL。

有些版本要求在调用pbuf_init()之前调用pbuf_alloc()。

你可以试试这个:

代码语言:javascript
复制
pkt_buf = NULL;//Use NULL, just incase the NULL is not 0 as per your compiler.
pkt_buf = pbuf_alloc(PBUF_TRANSPORT, bytesToSend, PBUF_REF);
if(pkt_buf == NULL)
{
   printf("pbuf_alloc failed.\n");
}
else
{
   /* Do something with the allocated pbufs and free it. */
}

PBUF_REF将不为pbuf分配缓冲区内存。pbuf应该只在一个线程中使用,如果pbuf排队,那么应该调用pbuf_take来复制缓冲区。

您也可以尝试PBUF_RAM,它将在内存中分配缓冲区。

要获得更多信息,您还可以浏览您正在使用的lwIP版本的源文件。

票数 7
EN

Stack Overflow用户

发布于 2012-06-18 13:40:27

最简单的解决方案似乎是使缓冲区static,即对每个调用重复使用相同的缓冲区:

代码语言:javascript
复制
static struct pbuf *pkt_buf = NULL;

if( pkt_buf == NULL )
    pkt_buf = pbuf_alloc(PBUF_TRANSPORT, bytesToSend, PBUF_POOL);
if( pkt_buf == NULL )
{
    print("(TFTP) Buffer overflow!\r\n");
}

如果您的场景涉及卸载/重新加载驱动程序,它将泄漏内存。要解决这个问题,在IAP_tftp_send_data_packet()函数之外使缓冲区保持静态,并在驱动程序卸载时调用pbuf_free() (假设lwip告诉您)。

票数 6
EN

Stack Overflow用户

发布于 2012-08-21 17:58:45

只是一个短暂的想法,可能是完全没有意义的。在此代码中:

代码语言:javascript
复制
if(bytesRead != 0) {
    bytesToSend = TFTP_DATA_PKT_LEN_MAX - (512 - bytesRead + 1);
} else {
    bytesToSend = TFTP_DATA_PKT_LEN_MAX - 512;
}
pkt_buf = pbuf_alloc(PBUF_TRANSPORT, bytesToSend, PBUF_POOL);

...is bytesRead是否有可能假定值为513 - TFTP_DATA_PKT_LEN_MAX?

如果发生这种情况,分配零字节的请求不会失败吗?(这可以通过在缓冲区溢出时打印bytesToSend的值并检查它是否为非零来进行测试)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11083931

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档