|
測試中發現有內存泄露的情況,通過增加內存的信息通過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以上的壓力數據下)
|
|