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

2019-10-31 17:35 [复制链接] 0 128

本帖最后由 moneng 于 2019-10-31 17:38 编辑
4 K% R; a4 J2 @, }9 Q0 T5 [- f! A% V. V& U' ]7 p& z8 v
之前用webclient-master时候遇到过内存泄漏,现在整理工程改成固定版本webclient-v2.1.0,感觉还是有泄漏现象,官方代码库更新一下把Bug去掉吧!
" D) M. N" E- T3 ], ?0 ^" H& T9 J. D7 m  s% b5 i
2019.07月份的笔记
! b; C* e. V4 g——————————————————————————————————
' c, Q( A5 F/ b# i9 |貌似存在内存泄漏# f9 E- T$ `& F. u1 F$ X
  1. msh />free9 [! x6 O- L. v4 J2 }: }. m
  2. total memory: 56464
    0 {# M: l* Q8 @
  3. used memory : 274722 U* K% @, p; @6 n
  4. maximum allocated memory: 30840# K8 c1 w3 w9 m' i& V
  5. msh />web_post_file_test
    , @- [, X1 r; i2 |6 D1 i7 Y
  6. [D/web] host address: 192.168.137.1 , port: 880
    ; w- q& {  r4 G9 P, w
  7. [D/web] request header:
    # ?8 A1 K6 m# F* l2 |3 J$ [
  8. [D/web] GET /web_upload/ HTTP/1.1  A3 w+ ~6 A' q6 o, }  Q
  9. [D/web] Host: 192.168.137.14 c( Q/ d* H. [
  10. [D/web] User-Agent: RT-Thread HTTP Agent
    6 S5 ?- B! r: P* ]

  11. 9 m3 h- G/ E. R! B3 G* b
  12. msh />free/ ~& }/ x; Y) I& P
  13. total memory: 56464) L) t2 h7 E0 i# y* U
  14. used memory : 31580
    & }$ J. \( t& ~3 M
  15. maximum allocated memory: 49408" L1 b" c" D2 K$ q
  16. msh />web_post_file_test
    ) @; \, T7 _. F* K; [% ]7 y, t7 Y* w7 i
  17. [D/web] host address: 192.168.137.1 , port: 880
    - c  }% ?/ l, X
  18. [D/web] request header:( X0 l* O# s. N
  19. [D/web] GET /web_upload/ HTTP/1.1% r2 U+ [" r8 ?0 b  S. y/ w
  20. [D/web] Host: 192.168.137.1
      ^$ B+ o% m! N3 m
  21. [D/web] User-Agent: RT-Thread HTTP Agent: \1 \% x9 F8 g1 k

  22. 6 C  Q( A2 ]+ d6 i0 M
  23. msh />free
    # w9 G1 j( Y2 M& O
  24. total memory: 56464% w) I6 }8 U  t
  25. used memory : 356883 C1 C4 a& q& k( x: I7 q
  26. maximum allocated memory: 53516, Z& p1 J: f* Y, n; A
  27. msh />web_post_file_test7 S8 w; f$ H8 v0 w7 \3 ]* z9 e
  28. [D/web] host address: 192.168.137.1 , port: 880& R8 S* h1 {5 Y. f$ D
  29. [D/web] request header:
    ! Q1 V; ~+ e) O" U# j$ z
  30. [D/web] GET /web_upload/ HTTP/1.1. f; |; B& F% V# W
  31. [D/web] Host: 192.168.137.18 |) ^& x4 ~& m) M0 U
  32. [D/web] User-Agent: RT-Thread HTTP Agent
    6 l1 _4 I$ N, z% T6 @
  33. 8 `6 h1 [6 w3 o
  34. [E/at.skt] no memory for esp8266 device(esp0) URC receive buffer(2920).
    ; Q' T. Z! ]+ N' Y1 y; z
  35. msh />
    ; J% T: L, J. V, c% m' g
复制代码
首先是发现 webclient_post_file 中在初始化 session->header 时没有处理 session->header->length
  e3 _8 y: W9 `& J: e5 c3 q
  1. //int webclient_post_file(const char* URI, const char* filename, const char* form_data)
    + q5 I6 F3 ^+ P0 o; ~' s7 m. k
  2. session->header->buffer = web_strdup(header);//附近没有session->header->length有关的代码
复制代码
之后发现 session->header->buffer = web_strdup(header); 语句貌似很危险
" m6 J; B/ m6 Y5 H尝试按web_post_test调用的webclient_post_comm的方式初始化header
; d* Y/ U- ?( J" W) u! l解决了之前怀疑的内存泄漏的问题
$ G. l& e2 M5 z4 t5 A) {接下来比较Fiddler向MVC发的File抓包,发现“Content-Length:”是在“boundary”里面的,遂改之
  1. /**9 U) `0 t0 i  G: L& w: U3 u
  2. * post file to http server.# @- v8 k* Z8 N8 G+ f6 F, a
  3. *
    9 }/ g& f  j& }8 C+ U) A+ V. o
  4. * @param URI input server address
    ! f/ A2 [2 G) ?6 {
  5. * @param filename post data filename( c3 y/ B' m: i  ~6 S$ m9 `4 L6 r: L! ?
  6. * @param form_data  form data+ i& S. a0 U& s9 \# `8 w
  7. *+ z: h- I' O( ~0 {5 z
  8. * @return <0: POST request failed) R! X  V3 c% v, I0 ^1 ^" k
  9. *         =0: success
    & e/ O; ?1 U9 [, P, R) D
  10. */
    $ V! z  g& ~9 Y) j% {
  11. #define webclient_post_file_backup (0)5 t; q3 T' ?; d2 ~; Y0 W6 [* @
  12. int webclient_post_file(const char* URI, const char* filename,, e) x7 M$ B% L# X) w
  13.         const char* form_data)
    2 x5 @6 H2 ]! q0 g2 i
  14. {
    # W6 h) ], O* j5 h
  15.     size_t length;
    2 v& f2 p; c6 W3 _/ f+ @+ C: ]
  16.     char boundary[60];
      y4 Q7 i, O" n5 X: |0 j
  17.     int fd = -1, rc = WEBCLIENT_OK;% I* Z( |$ w' e3 ]6 Q/ r# h
  18.     unsigned char *buffer = RT_NULL, *buffer_ptr;1 ~$ u' e1 W0 J3 c# d
  19.     struct webclient_session* session = RT_NULL;
    ) R8 ]4 ?2 I& g: \' R) A$ m3 X
  20. , ?" Q2 y* \2 W1 U+ N( ~; G
  21.     fd = open(filename, O_RDONLY, 0);
    1 Z4 {8 T% F" s$ {
  22.     if (fd < 0)
    2 h# z* a; v; N- Y
  23.     {
    $ i1 n  }' ^; n/ e: w8 ^) p
  24.         LOG_D("post file failed, open file(%s) error.", filename);
    - _# {8 e7 M" G
  25.         rc = -WEBCLIENT_FILE_ERROR;2 x. S1 b# ~6 N
  26.         goto __exit;4 B$ I) E; {6 [6 o8 ?  n5 c1 P/ s
  27.     }9 y' v& P; I: z) {* ?: A* E( D! N

  28. 3 U5 g; @7 O0 c1 k5 s
  29.     /* get the size of file */
    1 U7 d7 I( [% z+ k
  30.     length = lseek(fd, 0, SEEK_END);4 d6 r4 W2 K% ]1 C8 b' O) M
  31.     lseek(fd, 0, SEEK_SET);
      Q9 m6 d5 d6 G0 y$ {3 b7 Y$ Z

  32. ' c- {. h* h- I+ f5 A
  33.     buffer = (unsigned char *) web_malloc(WEBCLIENT_RESPONSE_BUFSZ);
    $ Y2 q0 A9 f4 \3 {0 Y- Q
  34.     if (buffer == RT_NULL)* h3 x1 G' m3 F2 f
  35.     {
    , E' e! Z; h. e
  36.         LOG_D("post file failed, no memory for response buffer.");; Q& A8 e& U* b3 s% [3 ~+ H
  37.         rc = -WEBCLIENT_NOMEM;
    & e# x, Q# c% k# F, X7 p9 T* a
  38.         goto __exit;
      b4 @4 `- e2 j! d0 \  t
  39.     }
    6 m1 ]+ M: d- x$ y% P7 F% \

  40. ; X+ W2 G  ^) ~* M3 V: {. G' D
  41.     #if webclient_post_file_backup6 b2 r; M/ L" [( g1 c
  42.     char *header = RT_NULL;
    # |0 ?) `! a& X8 n5 j
  43.     header = (char *) web_malloc(WEBCLIENT_HEADER_BUFSZ);
    0 i# Z/ @. U% [5 j6 E. @
  44.     if (header == RT_NULL)
    7 K. {8 T/ Q4 v! n4 V0 p
  45.     {% U; v" f+ }. W; p0 y/ d
  46.         LOG_D("post file failed, no memory for header buffer.");
    : m: E6 X! e3 V$ G9 h. `/ ?+ `0 P
  47.         rc = -WEBCLIENT_NOMEM;  O( d* n- z, B
  48.         goto __exit;
    $ D- s! [/ V" T& p. E* V+ T: \# G
  49.     }
    " O( t4 |0 ~. z0 G% e% L+ E
  50.     rt_memset(header,0,WEBCLIENT_HEADER_BUFSZ);
    ! U5 Z9 T- r( \! }/ E$ F3 ~& u
  51.     #endif
    3 o2 B) Q: ?+ L5 y

  52. & V6 e- t1 |) i# p' q6 o
  53.     /* build boundary */. x  H5 d. Q5 c3 C" W
  54.     rt_snprintf(boundary, sizeof(boundary), "----------------------------%012d", rt_tick_get());' P: s* Q" B0 \) r1 l( p. y

  55. ! |# r, [* a- i7 Z
  56.     /* build encapsulated mime_multipart information*/
    " R! s1 E. M/ @3 p5 d
  57.     buffer_ptr = buffer;3 \' @" z' g/ O% r/ _
  58.     /* first boundary */
    ( b, X. P, R7 `: B% f; @
  59.     buffer_ptr += rt_snprintf((char*) buffer_ptr,
    + w! D/ h' ]7 ?$ {- t6 i8 Q# d
  60.             WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer), "--%s\r\n", boundary);1 p8 S% _  W) B4 X7 r- V9 u
  61.     buffer_ptr += rt_snprintf((char*) buffer_ptr,
      l3 C/ p$ n8 A
  62.             WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer),
    * J& W" A1 j8 R8 a
  63.             "Content-Disposition: form-data; %s\r\n", form_data);
    9 t  ~1 R. k! c1 \: G+ o
  64.     buffer_ptr += rt_snprintf((char*) buffer_ptr,
    . h2 c2 r- s' |; Q: i3 A
  65.             WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer),- L% N# ~+ I& m2 ~
  66.             //"Content-Type: application/octet-stream\r\n\r\n");; h1 X3 o* H0 G4 G$ h1 G' s, ~
  67.             "Content-Type: image/jpeg\r\n\r\n");
    ! ~9 E2 P2 B8 ~% _0 K
  68.     /* calculate content-length */
    : d. ?8 _( V; B9 c8 M8 K+ k
  69.     length += buffer_ptr - buffer;% c. S9 i- |% s2 |
  70.     length += rt_strlen(boundary) + 6; /* add the last boundary */  I/ f: P" k3 ]& e9 ^5 _' g  l
  71. & R& L6 B4 U: r$ Z3 S
  72.     #if webclient_post_file_backup
    4 B4 ?4 N' B6 ^- c( r; J5 i
  73.     /* build header for upload */
    ! V5 e  g. d9 _0 y. H) _3 e; o
  74.     char *header_ptr;: m4 t$ [. I8 {# F  i0 b6 V: e7 L" @
  75.     header_ptr = header;) a$ k/ \0 k$ p+ ^
  76.     header_ptr += rt_snprintf(header_ptr,
    0 e# g1 S& A  ]+ X
  77.             WEBCLIENT_HEADER_BUFSZ - (header_ptr - header),8 I4 x8 \) X* ]0 d* o; c2 O9 e3 p
  78.             "Content-Length: %d\r\n", length);- W: K: K! k# o0 A
  79.     header_ptr += rt_snprintf(header_ptr,
    ) z7 K" @) D+ f; y, p
  80.             WEBCLIENT_HEADER_BUFSZ - (header_ptr - header),
    ! @. F' J3 |4 K6 [
  81.             "Content-Type: multipart/form-data; boundary=%s\r\n", boundary);: e9 ~' e" S8 @  W
  82. . d# ?0 G  o# ]
  83.     session = webclient_session_create(WEBCLIENT_HEADER_BUFSZ);( g% @6 w1 c9 Y/ ~# |" j% ?
  84.     if(session == RT_NULL)
    9 T$ K7 Y( h1 K2 p: \3 R
  85.     {
    # q# Y  f7 n% X" [! U& s! a
  86.         rc = -WEBCLIENT_NOMEM;
    2 J* J+ I) g' y! L2 f/ r; m0 H0 u
  87.         goto __exit;- Z. ~2 e$ C' P$ c4 D
  88.     }
    2 z- t2 ^' k5 |- f
  89. 5 o1 x" [/ h+ t$ u$ i8 i' s0 k
  90.     session->header->buffer = web_strdup(header);; n$ U2 m+ s; @, P5 X. x
  91.     //session->header->length = (size_t)(-1);
    $ x1 k' b! f: E# C9 C
  92.     #else4 S) \) d  I6 M6 F9 n
  93.     /* build header for upload */* Z9 W7 ~2 L  x
  94.     session = webclient_session_create(WEBCLIENT_HEADER_BUFSZ);! q6 l& O0 Z4 z  K  g3 S8 v' l; W
  95.     if(session == RT_NULL)
    . G6 D: a0 R, q% y2 _) n- ?
  96.     {$ b( `3 n" Z/ D( n! l5 Q4 T
  97.         rc = -WEBCLIENT_NOMEM;( M; M5 ~/ d5 k5 v* H8 s
  98.         goto __exit;
    / N* G+ U* a& ]/ Z  z) l4 o6 i
  99.     }
    ! U8 Q! `! B* M. O3 q
  100.     //session->header->buffer = web_strdup(header);0 w: m; X* _( P: c- a: _" s; D8 R; f
  101.     //调整"Content-Length:"到boundary内部
    + j2 T* D7 U0 w7 w
  102.     webclient_header_fields_add(session, "Content-Type: multipart/form-data; boundary=%s\r\n", boundary);
    + N# i1 v" n9 U* [' B# ^5 X% N8 g
  103.     webclient_header_fields_add(session, "Content-Length: %d\r\n", length);
    9 F5 W* ^; S! S
  104.     #endif& H; N! j$ E: `' o9 ?+ x1 J3 u6 i
  105.     ; j- x* x/ j2 v4 r5 l. L
  106.     rc = webclient_post(session, URI, NULL);7 h1 I; d2 T" m* @1 `
  107.     rt_thread_mdelay(100);
    5 E" @) |3 \6 I/ e( @* [# A
  108.     if( rc< 0)
    * h4 j1 Y1 b: M7 O+ q
  109.     {
    / S8 f- j9 L1 |) L+ Z+ _8 \
  110.         goto __exit;
    % W( J& B  `# N. ]' W2 h2 z# F. {
  111.     }2 I3 F0 N( ]' Y, |
  112. & Q$ G5 f$ z% w: r( [
  113.     /* send mime_multipart */
    # E1 {6 f" R. X, ^  ~' u$ \, {( F  K
  114.     webclient_write(session, buffer, buffer_ptr - buffer);. Y4 I4 h- e4 h) Q# _& E
  115.     rt_thread_mdelay(100);
    9 t' e0 f. M3 w
  116. % ?0 P) s5 Y; `( ^. u/ I. c( _
  117.     /* send file data */% J! z0 P7 E0 k. C/ y2 w# f
  118.     while (1)
    ' ]+ R: c) q1 v9 _, |; k- O
  119.     {. c4 {" Q# ?' i5 ~* J' X
  120.         length = read(fd, buffer, WEBCLIENT_RESPONSE_BUFSZ);
    8 e$ m5 O: K& ^; h
  121.         if (length <= 0)6 d9 @% S7 u7 \3 V6 H
  122.         {$ ^, X8 P# ?6 ]* v
  123.             break;
    - }- q* f3 s8 |+ z* q, i
  124.         }  X# \$ E/ ^4 N, _, b
  125. + \  R9 n; H8 u8 d8 ]! C
  126.         webclient_write(session, buffer, length);- C* N# c1 v& u9 V4 m5 S
  127.         rt_thread_mdelay(100);: j7 u) `. E' |
  128.     }
    ; h$ m) R: X* l8 ?

  129. ; g) [) C- l0 q0 z% |/ `$ A! V. H
  130.     /* send last boundary */
    7 y( l+ a4 L( o/ ]4 @
  131.     rt_snprintf((char*) buffer, WEBCLIENT_RESPONSE_BUFSZ, "\r\n--%s--\r\n", boundary);
    , H9 y3 F+ T& C. S, `
  132.     webclient_write(session, buffer, rt_strlen(boundary) + 6);2 i/ E: U: N; U: v) S
  133. - y; e7 v9 P" w" ]1 a6 |2 ]% u
  134. __exit:
    / M3 a: l1 Z; t: S
  135.     if (fd >= 0)
    ! C4 c; `7 u8 ]! G( G& V# p8 c/ F4 l
  136.     {4 A% s1 N  ~0 Z# o. B" G& R
  137.         close(fd);) A9 i" w& @- K! M$ P
  138.     }
    ! h5 A" w; O+ p0 {0 D+ Q
  139. 5 i! I( w( d8 c) J! ~
  140.     if (session != RT_NULL)' C- a9 j+ n8 h( g
  141.     {
    , Y" |, {4 b) E  D0 P
  142.         webclient_close(session);) q  E3 ^- o7 x9 i% u! @
  143.     }
    * v: c+ x) `  p  ?6 U
  144. 0 V2 M( M! m( W, g" N+ W( Z
  145.     if (buffer != RT_NULL)0 p$ e$ i  v0 C3 a/ i6 e0 ?1 f
  146.     {  m1 n$ ~6 X8 Y  ?! G! y
  147.         web_free(buffer);/ x- l1 |0 k8 r- I) O* v
  148.     }! a/ m- ]3 O/ U
  149. * b) @- M5 ]& ~
  150.     #if webclient_post_file_backup! L- V6 ?# Y% e: W# O
  151.     if (header != RT_NULL): L7 N. O( v4 t# w3 J9 B
  152.     {
    + [# g+ p: }- |! {$ s
  153.         web_free(header);
    4 T7 k, `7 O; }  U# M
  154.     }
    ( u2 I& u" a( C! A; X+ \& c" |5 p
  155.     #endif( c7 j4 ^8 I, [4 h/ U+ m
  156. / o, K1 W( G. t' S1 p# C
  157.     return 0;
    ; R8 K* H' G. J" o$ M5 a1 e
  158. }
复制代码

4 x: o$ y1 \9 _4 e9 d5 c
' G+ g1 K6 N# s3 \  m  Y  O8 D9 i: R% i" E3 x2 Q
+ d1 o- h5 u1 R$ B' P( P; j; X

5 [% [! V* J* w5 r" K
/ I  ?3 T4 y; i: y- O7 V8 z
6 w% z8 c+ e: d, Z$ N
使用道具 举报 显示全部楼层 回复
最新评论 | 正序浏览
显示全部楼层 |楼层直达:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|RT-Thread开发者社区 ( 沪ICP备13014002号-1

有害信息举报电话:021-31165890 手机:18930558079

© 2006-2019 上海睿赛德电子科技有限公司

Powered by RT-Thread

快速回复 返回顶部 返回列表