每次程序更改的 CRC 值为 运行
Value of CRC changing everytime program is run
我正在用 C 编写一个 CLI 实用程序,用于分析 PNG 文件并输出有关它的数据。更具体地说,它打印出 PNG 文件中每个块的长度、CRC 和类型值。我正在为 PNG 文件格式使用 official specification,它说每个块都有一个编码的 CRC 值以确保数据完整性。
我的工具 运行ning 很好,它输出正确的长度和类型值,并输出 看起来 的 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, sizeof(BYTE), 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, 1, sizeof(BYTE), png);
}
// Read CRC value
for(unsigned j = 0; j < 4; ++j) {
fread(&chunk.crc, 1, sizeof(BYTE), 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, 1, sizeof(BYTE), 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, sizeof(BYTE), png);
因为它不便携。您在 chunk.type
中的最终结果取决于它 运行 所在的体系结构的字节顺序。对于“IHDR”,您将在小端机器上获得 0x52444849
,在大端机器上获得 0x49484452
。
我正在用 C 编写一个 CLI 实用程序,用于分析 PNG 文件并输出有关它的数据。更具体地说,它打印出 PNG 文件中每个块的长度、CRC 和类型值。我正在为 PNG 文件格式使用 official specification,它说每个块都有一个编码的 CRC 值以确保数据完整性。
我的工具 运行ning 很好,它输出正确的长度和类型值,并输出 看起来 的 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, sizeof(BYTE), 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, 1, sizeof(BYTE), png);
}
// Read CRC value
for(unsigned j = 0; j < 4; ++j) {
fread(&chunk.crc, 1, sizeof(BYTE), 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, 1, sizeof(BYTE), 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, sizeof(BYTE), png);
因为它不便携。您在 chunk.type
中的最终结果取决于它 运行 所在的体系结构的字节顺序。对于“IHDR”,您将在小端机器上获得 0x52444849
,在大端机器上获得 0x49484452
。