zlib inflate() 在解压缩缓冲区时部分挂起

问题描述 投票:0回答:1

我在 MicroChip/XC32 上使用 zlib 1.3.1。它是通过附带的 Harmony 导入的,并且翻译得非常完美。我的目标是通过各种方式通过串行连接接收数据。这已经适用于未压缩的数据。为了节省时间,我想压缩数据,并使用 4k、8k 和现在 16k 的未压缩二进制数据块进行了测试。我在循环内传输数据并在微控制器上对其进行 inflate() 。

为了传输数据块,我使用 Python3.6 导入 zlib( 1.2.10 ) 。

代码是:

  # create compressor with user defined options
  compressor = zlib.compressobj( level=zlib.Z_BEST_COMPRESSION, wbits=zlib.MAX_WBITS )
  
  data = compressor.compress(datablock) + compressor.flush() # datablock size is 16k

  send the data ...

单片机接收到rcvbuf[]中的数据后代码为:

#include "zlib.h"

uint8_t             rcv_buf[LEN_RCV_BUF];              // LEN_RCV_BUF = 17000
//uint8_t             decompress_buf[LEN_RCV_BUF];
uint8_t             decompress_buf[40000];             // increased for testing
uint8_t             my_adr[40000];                     // increased for testing




/*
*
* rcv_buf is already filled, when this function is called
*
*
*/
void cmd_write_to_myadr(void) {


volatile z_stream   out_stream;   // zlib struct
uint16_t            have;
int                 ret;    
uint16_t            dat_len = ( rcv_buf[5] << 8 ) + rcv_buf[6];



/* allocate inflate state */
out_stream.zalloc     = Z_NULL;
out_stream.zfree      = Z_NULL;
out_stream.opaque     = Z_NULL;
out_stream.avail_in   = 0;
out_stream.next_in    = Z_NULL;

ret = inflateInit( &out_stream ); // HEAP-Size

if( ret != Z_OK ) {
  
//                      return ret;                 
  
  // neg_response(); // AAA
  return; 
}


// rcv_buf[7];     =>    != 0 means data is compressed !

out_stream.avail_in    =  dat_len;
out_stream.next_in     = &rcv_buf[8];
out_stream.avail_out   =  sizeof( decompress_buf );
out_stream.next_out    = &decompress_buf[0];


// run DE-compression 
ret = inflate( &out_stream,  Z_NO_FLUSH );

assert(ret != Z_STREAM_ERROR);  /* state not clobbered */

switch( ret ) {
  
  case Z_NEED_DICT  :
    ret = Z_DATA_ERROR;     /* and fall through */
  case Z_DATA_ERROR :
  case Z_MEM_ERROR  :
    inflateEnd( &out_stream );
//                            return ret;
//              negativ_response();
  return;                             // BreakPoint is here !!!
  case Z_STREAM_END :
    break;
  default:
    return;                           // BreakPoint is here !!!
}

have = sizeof( decompress_buf ) - out_stream.avail_out;
memWrite_sram_buffer( my_adr, &decompress_buf[0], have );
my_adr += have;


inflateEnd( &out_stream );

}

我正在传输二进制数据(图像和代码)。

事情是,取决于压缩数据块的内容,它是否有效。

我尝试了不同的选项和窗口大小,但在不同的调用 inflate() 后我总是遇到同样的问题。

在 inflate() 函数之后设置断点向我表明它挂在那里。

目前使用Python3仅用于测试,稍后将替换为C++代码。

是因为使用了两个不同版本的zlib进行压缩(deflate)和inflate吗?

zlib
1个回答
0
投票

OP似乎不愿意提供可以在问题中编译的完整代码,也不愿意提供任何运行它的测试代码和测试用例,但是在对其最新更新进行一些工作之后,我得到了这个编译(请参阅 %% 评论改变了什么):

#include <assert.h>                             // %% added for assert()
#include "zlib.h"

#define LEN_RCV_BUF 17000                       // %% added

uint8_t             rcv_buf[LEN_RCV_BUF];              // LEN_RCV_BUF = 17000
//uint8_t             decompress_buf[LEN_RCV_BUF];
uint8_t             decompress_buf[40000];             // increased for testing
uint8_t             my_adr[40000];                     // increased for testing

/*
 *
 * rcv_buf is already filled, when this function is called
 *
 */
unsigned cmd_write_to_myadr(void) {             // %% added returned length

    z_stream   out_stream;   // zlib struct  %% removed "volatile"
    uint16_t            have;
    int                 ret;
    uint16_t            dat_len = ( rcv_buf[5] << 8 ) + rcv_buf[6];

    /* allocate inflate state */
    out_stream.zalloc     = Z_NULL;
    out_stream.zfree      = Z_NULL;
    out_stream.opaque     = Z_NULL;
    out_stream.avail_in   = 0;
    out_stream.next_in    = Z_NULL;

    ret = inflateInit( &out_stream ); // HEAP-Size

    if( ret != Z_OK ) {
        //                      return ret;

        // neg_response(); // AAA
        return 0;
    }

    // rcv_buf[7];     =>    != 0 means data is compressed !

    out_stream.avail_in    =  dat_len;
    out_stream.next_in     = &rcv_buf[8];
    out_stream.avail_out   =  sizeof( decompress_buf );
    out_stream.next_out    = &decompress_buf[0];

    // run DE-compression
    ret = inflate( &out_stream,  Z_NO_FLUSH );

    assert(ret != Z_STREAM_ERROR);              /* state not clobbered */

    switch( ret ) {

    case Z_NEED_DICT  :
        ret = Z_DATA_ERROR;                     /* and fall through */
    case Z_DATA_ERROR :
    case Z_MEM_ERROR  :
        inflateEnd( &out_stream );
        //                            return ret;
        //              negativ_response();
        return 0;                               // BreakPoint is here !!!
    case Z_STREAM_END :
        break;
    default:
        return 0;                               // BreakPoint is here !!!
    }

    have = sizeof( decompress_buf ) - out_stream.avail_out;

    // %% commenting out undefined function and illegal arithmetic on constant
    // %% pointer
    // %% memWrite_sram_buffer( my_adr, &decompress_buf[0], have );
    // %% my_adr += have;

    inflateEnd( &out_stream );
    return have;                                // %% added
}

#include <stdio.h>

int main(void) {
    size_t got = fread(rcv_buf + 8, 1, sizeof(rcv_buf) - 8, stdin);
    rcv_buf[5] = got >> 8;
    rcv_buf[6] = got;
    unsigned have = cmd_write_to_myadr();
    fwrite(decompress_buf, 1, have, stdout);
    return 0;
}

我使用 zlib 压缩数据运行此程序,并且它正确解压。没有对原始代码进行实质性更改,因此问题出在其他地方。也许在数据生成中,包括两个字节长度的标头,在压缩数据的放置中(同样,OP提供了不完整的Python代码来生成测试数据),或者在数据的传输和接收中。

© www.soinside.com 2019 - 2024. All rights reserved.