感觉webclient里的webclient_file存在内存泄漏

发布于 2019-10-31 17:35:49
    本帖最后由 moneng 于 2019-10-31 17:38 编辑


之前用webclient-master时候遇到过内存泄漏,现在整理工程改成固定版本webclient-v2.1.0,感觉还是有泄漏现象,官方代码库更新一下把Bug去掉吧!

2019.07月份的笔记
——————————————————————————————————
貌似存在内存泄漏
msh />free
total memory: 56464
used memory : 27472
maximum allocated memory: 30840
msh />web_post_file_test
[D/web] host address: 192.168.137.1 , port: 880
[D/web] request header:
[D/web] GET /web_upload/ HTTP/1.1
[D/web] Host: 192.168.137.1
[D/web] User-Agent: RT-Thread HTTP Agent

msh />free
total memory: 56464
used memory : 31580
maximum allocated memory: 49408
msh />web_post_file_test
[D/web] host address: 192.168.137.1 , port: 880
[D/web] request header:
[D/web] GET /web_upload/ HTTP/1.1
[D/web] Host: 192.168.137.1
[D/web] User-Agent: RT-Thread HTTP Agent

msh />free
total memory: 56464
used memory : 35688
maximum allocated memory: 53516
msh />web_post_file_test
[D/web] host address: 192.168.137.1 , port: 880
[D/web] request header:
[D/web] GET /web_upload/ HTTP/1.1
[D/web] Host: 192.168.137.1
[D/web] User-Agent: RT-Thread HTTP Agent

[E/at.skt] no memory for esp8266 device(esp0) URC receive buffer(2920).
msh />
首先是发现 webclient_post_file 中在初始化 session->header 时没有处理 session->header->length
//int webclient_post_file(const char* URI, const char* filename, const char* form_data)
session->header->buffer = web_strdup(header);//附近没有session->header->length有关的代码
之后发现 session->header->buffer = web_strdup(header); 语句貌似很危险
尝试按web_post_test调用的webclient_post_comm的方式初始化header
解决了之前怀疑的内存泄漏的问题
接下来比较Fiddler向MVC发的File抓包,发现“Content-Length:”是在“boundary”里面的,遂改之
/**
* post file to http server.
*
* @param URI input server address
* @param filename post data filename
* @param form_data form data
*
* @return <0: POST request failed
* =0: success
*/
#define webclient_post_file_backup (0)
int webclient_post_file(const char* URI, const char* filename,
const char* form_data)
{
size_t length;
char boundary[60];
int fd = -1, rc = WEBCLIENT_OK;
unsigned char *buffer = RT_NULL, *buffer_ptr;
struct webclient_session* session = RT_NULL;

fd = open(filename, O_RDONLY, 0);
if (fd < 0)
{
LOG_D("post file failed, open file(%s) error.", filename);
rc = -WEBCLIENT_FILE_ERROR;
goto __exit;
}

/* get the size of file */
length = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);

buffer = (unsigned char *) web_malloc(WEBCLIENT_RESPONSE_BUFSZ);
if (buffer == RT_NULL)
{
LOG_D("post file failed, no memory for response buffer.");
rc = -WEBCLIENT_NOMEM;
goto __exit;
}

#if webclient_post_file_backup
char *header = RT_NULL;
header = (char *) web_malloc(WEBCLIENT_HEADER_BUFSZ);
if (header == RT_NULL)
{
LOG_D("post file failed, no memory for header buffer.");
rc = -WEBCLIENT_NOMEM;
goto __exit;
}
rt_memset(header,0,WEBCLIENT_HEADER_BUFSZ);
#endif

/* build boundary */
rt_snprintf(boundary, sizeof(boundary), "----------------------------%012d", rt_tick_get());

/* build encapsulated mime_multipart information*/
buffer_ptr = buffer;
/* first boundary */
buffer_ptr += rt_snprintf((char*) buffer_ptr,
WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer), "--%s\r\n", boundary);
buffer_ptr += rt_snprintf((char*) buffer_ptr,
WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer),
"Content-Disposition: form-data; %s\r\n", form_data);
buffer_ptr += rt_snprintf((char*) buffer_ptr,
WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer),
//"Content-Type: application/octet-stream\r\n\r\n");
"Content-Type: image/jpeg\r\n\r\n");
/* calculate content-length */
length += buffer_ptr - buffer;
length += rt_strlen(boundary) + 6; /* add the last boundary */

#if webclient_post_file_backup
/* build header for upload */
char *header_ptr;
header_ptr = header;
header_ptr += rt_snprintf(header_ptr,
WEBCLIENT_HEADER_BUFSZ - (header_ptr - header),
"Content-Length: %d\r\n", length);
header_ptr += rt_snprintf(header_ptr,
WEBCLIENT_HEADER_BUFSZ - (header_ptr - header),
"Content-Type: multipart/form-data; boundary=%s\r\n", boundary);

session = webclient_session_create(WEBCLIENT_HEADER_BUFSZ);
if(session == RT_NULL)
{
rc = -WEBCLIENT_NOMEM;
goto __exit;
}

session->header->buffer = web_strdup(header);
//session->header->length = (size_t)(-1);
#else
/* build header for upload */
session = webclient_session_create(WEBCLIENT_HEADER_BUFSZ);
if(session == RT_NULL)
{
rc = -WEBCLIENT_NOMEM;
goto __exit;
}
//session->header->buffer = web_strdup(header);
//调整"Content-Length:"到boundary内部
webclient_header_fields_add(session, "Content-Type: multipart/form-data; boundary=%s\r\n", boundary);
webclient_header_fields_add(session, "Content-Length: %d\r\n", length);
#endif

rc = webclient_post(session, URI, NULL);
rt_thread_mdelay(100);
if( rc< 0)
{
goto __exit;
}

/* send mime_multipart */
webclient_write(session, buffer, buffer_ptr - buffer);
rt_thread_mdelay(100);

/* send file data */
while (1)
{
length = read(fd, buffer, WEBCLIENT_RESPONSE_BUFSZ);
if (length <= 0)
{
break;
}

webclient_write(session, buffer, length);
rt_thread_mdelay(100);
}

/* send last boundary */
rt_snprintf((char*) buffer, WEBCLIENT_RESPONSE_BUFSZ, "\r\n--%s--\r\n", boundary);
webclient_write(session, buffer, rt_strlen(boundary) + 6);

__exit:
if (fd >= 0)
{
close(fd);
}

if (session != RT_NULL)
{
webclient_close(session);
}

if (buffer != RT_NULL)
{
web_free(buffer);
}

#if webclient_post_file_backup
if (header != RT_NULL)
{
web_free(header);
}
#endif

return 0;
}







查看更多

关注者
0
被浏览
341
0 个回答
暂无答案,快来添加答案吧

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友