首先来说一下问题是怎么产生的?
在Ubuntu15.10上面从apt源里下载zip的源代码,然后对源代码进行编译,但是在编译时要使用-DUSE_ZLIB选项,以及-lz链接系统中的zlib库。
编译成功以后对linux-4.3内核的源码进行压缩:$./zip -r linux-4.3.zip linux-4.3,就会一直卡死在adding: net/wireless/.gitignore文件,对这个文件中的内容查看,里面只有“regdb.c”这些内容。
解决方法:经过测试发现,任意创建一个新文件,往文件中写一些内容,当压缩率在1%以下时就会出现该错误,然后对比zip压缩中的bz2压缩函数bzfilecompress()与zlib压缩函数filecompress(),其压缩流程基本上一致,只是zlib与bz2相比少了“FILE *zipfile = y;”一条语句,从而使fseekable(zipfile)判断在执行时使用的是全局变量char *zipfile;//这个变量在global.c文件里,而fseekable(zipfile)中的zipfile变量是FILE*类型的,所以会出现错误。
附:Zip3.0的源码可以在这里下载 http://www.info-zip.org
下面是一些追踪调试的过程:
对测试程序使用valgrind进行定位,输出为
==21166== Command: zip test.zip mytest
==21166==
adding: mytest==21166== Invalid read of size 8
==21166== at 0x52DA275: fseeko (fseeko.c:38)
==21166== by 0x41A343: fseekable (util.c:84)
==21166== by 0x4132A8: filecompress (zipup.c:1544)
==21166== by 0x4132A8: zipup (zipup.c:842)
==21166== by 0x4062FF: main (zip.c:5557)
最后找到是在fseeko 函数里出现Segment fault错误。
然后再使用ltrace追踪:
open64("mytest2", 0, 00) = 4
malloc(1024) = 0x1de3850
fwrite("PK\003\004\024", 1, 65, 0x1ddf550) = 65
free(0x1de3850) = <void>
ferror(0x1ddf550) = 0
ftello64(0x1ddf550, 1, 0, 0xfbad0085) = 65
ferror(0x1ddf550) = 0
malloc(16384) = 0x1de3850
malloc(16384) = 0x1de7860
zlibVersion(3, 0, 0x1de7860, 0x7f2dd172cc00) = 0x7f2dd17488b4
zlibVersion(3, 0, 0x1de7860, 0x7f2dd172cc00) = 0x7f2dd17488b4
deflateInit2_(0x62b860, 6, 8, 0xfffffff1) = 0
read(4, "12345678901\n", 16384) = 12
crc32(0, 0x1de3850, 12, 0x7f2dd145f480) = 0x75365308
read(4, "", 16372) = 0
deflate(0x62b860, 4, 0xffffffff, 0x7f2dd145f480) = 1
fseeko64(0x1ddf050, -1, 1, 28
//一直卡在fseeko64函数
使用strce追踪:
open("mytest2", O_RDONLY) = 4
brk(0x24d0000) = 0x24d0000
write(1, "***err=0, level=6***\n", 21***err=0, level=6***
) = 21
read(4, "12345678901\n", 16384) = 12
read(4, "", 16372) = 0
futex(0x7f0e4cbc0c68, FUTEX_WAIT_PRIVATE, 2, NULL
//一直卡在futex函数