0

这几天我一直在追一个非常神秘的错误,它似乎围绕着(ZLIB 库);它每月左右发生一次,并且仅在某些特定的生产环境中发生。以下是代码的作用:

  1. 程序调用gzopen写入文件X
  2. 程序将数据写入文件,执行几个gzwrite.
  3. 程序最终调用gzclose它刷新文件。

通常,一切正常,文件X有效;它以 CRC 和源流的长度正确终止。

但是,在其中一个故障中,我观察到这X是损坏的:数据的开头是正确的,但是从 offset 开始0x00302000,每个字节都是空的。即使是编码 CRC 和长度的最后八个字节也为零。但是,该文件具有正确的大小!更糟糕的是:同一个系统在几分钟前成功压缩了一个非常相似的文件。

注意:我们使用的 ZLIB.DLL 版本为 1.1.3;是的,我知道,它包含一些安全漏洞,我们应该升级到最新的 ZLIB 1.2.3,但在找到归零的原因之前,我不想更改我的设置中的任何内容。

我认为我已经排除了内存损坏(顺便说一下,损坏的内存堆怎么会干扰fwrite到它只向输出流写入零?这是否合理?),打开/写入/关闭流的循环很简单,没有发现我能发现的任何缺陷,代码不会分配/释放/弄乱 ZLIB 中的结构(这可能是个问题,因为 ZLIB 链接到另一个 C 库而不是我的应用程序 DLL),所以我只能怀疑系统中的其他元素。

不知何故,我倾向于对 C 库 (CRTDLL.DLL)、Win32 API、NTFS 堆栈、I/O 堆栈、低级设备驱动程序、硬盘固件和硬盘本身充满信心......是的,我也倾向于相信 Visual C++ 2008 会生成正确的二进制文件,至少在这种情况下是这样 ;-)

那么,我是否正确怀疑杀毒软件可能是罪魁祸首?ZLIB 应该谨慎,因为至少 Kaspersky 将 DLL 识别为可能的威胁。但是,如果(错误地)发现感染,杀毒软件只写零而不是数据在政治上是否正确?或者这可能是防病毒软件中的错误?

还是我完全错过了重点?

4

1 回答 1

1

在不知道其他任何事情的情况下,我会怀疑您的代码,而不是防病毒代码。

将正确长度的数据写入文件需要一个简单的错误,但传入的缓冲区不正确,导致文件中的数据“全为零”。

很难发现的简单错误有时会导致非常大的混乱,就像你遇到的那样。

如果我对此进行故障排除,我会:

  • 简化 简化 简化,直到问题停止。然后逐步添加复杂性。
  • 检查你的指针和指针算术
  • 检查您是否正确刷新和关闭文件
  • 使用分配器将标记字节存储在分配的缓冲区中,例如 0xAA 而不是 0x00。通过这种方式,您可以查看正在写入文件的是否是您的(归零)缓冲区。
  • 在调试器中逐步完成所有操作

在正常情况下,经过 GZIP 压缩的数据永远不会有很长的连续零。这些将被折叠成字典和长度代码。

于 2009-06-02T18:52:56.943 回答