|
测试中发现有内存泄露的情况,通过增加内存的信息通过TCP输出的 2301端口debug后发现
异常的如下
总内存数(字节):6144
已用内存(字节):5816
剩余内存数(字节):328
使用标示:1
正常的如下
总内存数(字节):6144
已用内存(字节):20
剩余内存数(字节):6124
使用标示:1
显然memalloc使内存溢出查找代码因为除了SMTP应用程序使用malloc外其他不具有使用的情况。
所以肯定是SMTP出问题
进一步分析代码为SMTP的smtp_send_mail()中
smtp_send_mail_alloced(struct smtp_session *s)
函数使用的
s = (struct smtp_session *)SMTP_STATE_MALLOC((mem_size_t)mem_len);
分配了一块内存没有事正常的释放。
这样反复
几次最终导致这块应用代码不能正常返回一块完整的 mem_le大小的内存块而一直保留了328字节的剩余内存。
这最终导致了所有依赖mem的应用程序全部获取不到足够的内存块。而出现的内存溢出。
继续分析 释放的内存句柄 (struct smtp_session *) s
发现几处问题
1)非正常中止 “风险”
if (smtp_verify(s->to, s->to_len, 0) != ERR_OK) {
return ERR_ARG;
}
if (smtp_verify(s->from, s->from_len, 0) != ERR_OK) {
return ERR_ARG;
}
if (smtp_verify(s->subject, s->subject_len, 0) != ERR_OK) {
return ERR_ARG;
}
由于没有对 smtp_send_mail_alloced 函数进行判断所以如果此处返回会造成函数不能正常中止
也就会导致 (struct smtp_session *) s 没有机会释放(因为在不正常中止时是在后面处理的)
但是考虑到源数据是固定的从片上flash中取得的,这种几率几乎没有。但是存在风险。所以统一改为
if (smtp_verify(s->to, s->to_len, 0) != ERR_OK) {
err = ERR_ARG;
goto leave;
}
if (smtp_verify(s->from, s->from_len, 0) != ERR_OK) {
err = ERR_ARG;
goto leave;
}
if (smtp_verify(s->subject, s->subject_len, 0) != ERR_OK) {
err = ERR_ARG;
goto leave;
}
2)、非正常TCP连接,主要原因。
原来的函数为:
if(tcp_bind(pcb, IP_ADDR_ANY, SMTP_PORT)!=ERR_OK)
{
return ERR_USEl;
}
显然还是同样的会造成malloc 分配了但是没有被调用,修改为
if(tcp_bind(pcb, IP_ADDR_ANY,SMTP_PORT)!=ERR_OK)
{
err = ERR_USE;
goto leave;
}
这样 leave中就会自动处理释放掉这个非正常中止的而造成的内存的溢出问题。
leave:
smtp_free_struct(s);
return err;
归根结底是一个问题。那就是必须保证malloc 和free 成对出现。
实际验证时发现就是tcp_bind的时反回了(在100K以上的压力数据下)
|
|