zlib inflateReset导致内存泄漏(不是)

时间:2015-12-23 03:13:59

标签: c memory-leaks zlib inflate

我目前正致力于以下要求。 这是要求:在服务器端,大文件被分成4000字节块(帧)。每个块依次压缩(使用zlib)并发送到客户端进程。例如,如果文件大小为12000字节,则将其分为3个块。

上面的文件将有3个块=> Block-1 Block-1 Block-0

收到后,客户端解压缩每个块(或帧)并写入堆上分配的缓冲区。当客户端收到与整个文件对应的所有块时,生成的文件的未压缩版本将写入磁盘。

我编写了一个例程inflateData,根据收到的块#

执行以下操作

收到第一个街区时,    - inflateInit    - 膨胀    - inflateReset 当收到中间块时,    - 膨胀    - inflateReset 收到最后一个块时    - 膨胀    - inflateEnd

通过上述例程,块的解压缩按预期发生。但是我面临的问题是它消耗了大量内存,并且在某些时候整个系统都会变慢。使用valgrind检查时,会报告inflateInit2_的内存泄漏。这会导致系统资源耗尽。

  

== 30359 == 6个街区中的57,312个字节可能在67个损失记录中丢失

     

== 30359 ==在0x4A069EE:malloc(vg_replace_malloc.c:270)

     

== 30359 == by 0x3E57808F1E:inflateInit2_(in /lib64/libz.so.1.2.3)

     

== 30359 == by 0x40C220:inflateData(productMaker.c:1668)

以下是例程inflateData。

    int inflateData(
    char*    const    inBuf,                  
    unsigned long     inLen,                  
    unsigned int      isFirstBlk,
    unsigned int      isLastBlk,
    const    char*    outBuf,                 
    unsigned long*     outLen)                 
{

  int have;
  int readsz;
  int bsize;
  static z_stream zstrm;
  int zerr;
  int flush;
  char out[CHUNK_SZ];
  char in[CHUNK_SZ];
  int ret,nwrite,idx = -1;
  int savedByteCntr=0;
  unsigned char *dstBuf;
  int  firstCall = 1;
  int totalBytesIn=0;
  int inflatedBytes=0;
  int decompByteCounter = 0;
  int num=0;


  ret = Z_OK;
  readsz = 0;
  bsize = CHUNK_SZ;

  dstBuf = (unsigned char *) outBuf;

  if(isFirstBlk){
        memset(&zstrm, '\0', sizeof(z_stream));
        zstrm.zalloc = Z_NULL;
        zstrm.zfree = Z_NULL;
        zstrm.opaque = Z_NULL;

        if ((zerr = inflateInit(&zstrm)) != Z_OK) {
                uerror("ERROR %d inflateInit (%s)",
                        zerr, decode_zlib_err(zerr));
                return -1;
        }
  }

    while(totalBytesIn < inLen ) {
      int compChunkSize = ((inLen - totalBytesIn) > 5120) ? 5120 :
                                                  (inLen - totalBytesIn);
      memcpy(in, inBuf + totalBytesIn, compChunkSize);

      zstrm.avail_in = inLen - totalBytesIn;
      zstrm.next_in = in ;

      zstrm.avail_out = CHUNK_SZ;
      zstrm.next_out = out;
      inflatedBytes = 0;

      while(ret != Z_STREAM_END) {
         ret  = inflate(&zstrm, Z_NO_FLUSH);
         if(ret < 0) {
          uerror(" Error %d inflate (%s)", ret, decode_zlib_err(ret));
          (void)inflateEnd(&zstrm);
           return ret;
         }
         inflatedBytes = CHUNK_SZ - zstrm.avail_out;

         if(inflatedBytes == 0) {
              unotice("\n Unable to decompress data - truncated");
              break;
         }
     totalBytesIn += zstrm.total_in;
     decompByteCounter += inflatedBytes;

     memcpy(dstBuf + savedByteCntr, out, inflatedBytes);
     savedByteCntr = decompByteCounter;
   }

   // Reset inflater for additional input
   ret = inflateReset(&zstrm);
   if(ret == Z_STREAM_ERROR){
      uerror(" Error %d inflateReset (%s)", ret, decode_zlib_err(ret));
      (void)inflateEnd(&zstrm);
       return ret;
   }
  }

if(isLastBlk){
 ret = inflateEnd(&zstrm);
 if(ret < 0) {
   uerror("Fail inflateEnd %d [%s] ", ret, decode_zlib_err(ret));
   return (ret);
 }
}

  *outLen = decompByteCounter;
   return 0;
}

提前感谢您的支持。

谢谢, 沙迪亚。

1 个答案:

答案 0 :(得分:1)

您在使用inflateData()例程时出错。

首先,以这种方式使用静态变量是一个可怕的想法。如果您使用inflateData()两次调用isFirstBlk而没有isLastBlkzstrm的中间调用,那么您将清除对第一组分配的引用,从而导致内存泄漏。< / p>

要避免此类错误,您应该跟踪isFirstBlk是否已初始化,并拒绝任何初始化已初始化的流的尝试。更好的是,甚至没有zstrm,只需在第一次通话时以及在isLastBlkisFirstBlk的电话后立即进行的任何通话中初始化isLastBlk

因此,您要么执行上述操作,请使用function Duck() {} Duck.prototype.quack = function() {alert('Quaaaaaack!');}; Duck.prototype.feathers = function() {alert('The duck has white and gray feathers.');}; //Duck.prototype.name = function() {alert('Donald Duck');}; function Person() {} Person.prototype.quack = function() {alert('The person imitates a duck.');}; Person.prototype.feathers = function() {alert('The person takes a feather from the ground and shows it.');}; Person.prototype.name = function() {alert('Rick James');}; function inTheForest(object) { object.quack(); object.feathers(); object.name(); } function game() { var donald = new Duck(); var john = new Person(); inTheForest(donald); inTheForest(john); } game(); true调用两次,否则无法使用 var cors = new EnableCorsAttribute("*", "*", "*"); config.EnableCors(cors); 调用true。