如何解决每次程序运行时CRC的值都会改变
我正在用 C 语言编写一个 CLI 实用程序,用于分析 PNG 文件并输出有关它的数据。更具体地说,它打印出 PNG 文件中每个块的长度、CRC 和类型值。我将 official specification 用于 PNG 文件格式,它表示每个块都有一个 CRC 值编码在其中以确保数据完整性。
我的工具运行良好,它输出正确的长度和类型值,并输出看起来是 CRC 的正确值(因为它被格式化为 4 字节的十六进制) -唯一的问题是每次我运行这个程序时,CRC 的值都会改变。这是否正常,如果不正常,可能是什么原因造成的?
这是代码的主要部分
CHUNK chunk;
BYTE buffer;
int i = 1;
while (chunk.type != 1145980233) { // 1145980233 is a magic number that signals our program that IEND chunk
// has been reached it is just the decimal equivalent of 'IEND'
printf("============\nCHUNK: %i\n",i);
// Read LENGTH value; we have to buffer and then append to length hexdigit-by-hexdigit to account for
// reversals of byte-order when reading infile (im not sure why this reversal only happens here)
for(unsigned j = 0; j < 4; ++j) {
fread(&buffer,1,sizeof(BYTE),png);
chunk.length = (chunk.length | buffer)<<8; // If length is 0b4e and buffer is 67 this makes sure that length
// ends up 0b4e67 and not 0b67
}
chunk.length = chunk.length>>8; // Above bitshifting ends up adding an extra 00 to end of length
// This gets rid of that
printf("LENGTH: %u\n",chunk.length);
// Read TYPE value
fread(&chunk.type,4,png);
// Print out TYPE in chars
printf("TYPE: ");
printf("%c%c%c%c\n",chunk.type & 0xff,(chunk.type & 0xff00)>>8,(chunk.type & 0xff0000)>>16,(chunk.type & 0xff000000)>>24);
// Allocate LENGTH bytes of memory for data
chunk.data = calloc(chunk.length,sizeof(BYTE));
// Populate DATA
for(unsigned j = 0; j < chunk.length; ++j) {
fread(&buffer,png);
}
// Read CRC value
for(unsigned j = 0; j < 4; ++j) {
fread(&chunk.crc,png);
}
printf("CRC: %x\n",chunk.crc);
printf("\n");
i++;
}
这里是一些预处理器指令和全局变量
#define BYTE uint8_t
typedef struct {
uint32_t length;
uint32_t type;
uint32_t crc;
BYTE* data;
} CHUNK;
这里是我得到的输出的一些例子
运行 1 -
============
CHUNK: 1
LENGTH: 13
TYPE: IHDR
CRC: 17a6a400
============
CHUNK: 2
LENGTH: 2341
TYPE: iCCP
CRC: 17a6a41e
运行 2 -
============
CHUNK: 1
LENGTH: 13
TYPE: IHDR
CRC: 35954400
============
CHUNK: 2
LENGTH: 2341
TYPE: iCCP
CRC: 3595441e
运行 3 -
============
CHUNK: 1
LENGTH: 13
TYPE: IHDR
CRC: 214b0400
============
CHUNK: 2
LENGTH: 2341
TYPE: iCCP
CRC: 214b041e
如您所见,CRC 值每次都不同,但在每次运行中它们都非常相似,而我的直觉告诉我这不应该是这种情况,CRC 值不应该改变。
为了确保,我也跑了
$ cat test.png > file1
$ cat test.png > file2
$ diff -s file1 file2
Files file1 and file2 are identical
因此,两次不同时间访问该文件并不会像预期的那样更改其中的 CRC 值。
谢谢,
解决方法
这个:
fread(&chunk.crc,1,sizeof(BYTE),png);
继续用从文件中读取的字节覆盖 chunk.crc
的第一个字节。 chunk.crc
的其他三个字节永远不会被写入,因此当您的程序启动时,您会在这些位置随机看到内存中的任何内容。您会注意到末尾的 00
和 1e
是一致的,因为这是正在写入的一个字节。
在您的数据读取循环中也有同样的问题:
fread(&buffer,png);
一个不相关的错误是您在 32 位整数中累积字节:
chunk.length = (chunk.length | buffer)<<8;
然后在该循环结束后,将其回滚:
chunk.length = chunk.length>>8;
这将始终丢弃长度的最高有效字节,因为您将其从 32 位的顶部推出,然后将八个零位回滚到其位置。相反,您需要这样做:
chunk.length = (chunk.length << 8) | buffer;
然后所有的32位都保留了,最后就不用修了。
这是个坏主意:
fread(&chunk.type,4,png);
因为它不便携。您在 chunk.type
中的最终结果取决于它运行的架构的字节序。对于“IHDR”,您将在小端机器上获得 0x52444849
,在大端机器上获得 0x49484452
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。