不依赖第三方库用C语言读取PNG文件签名输出异常咨询
异常原因
- 数组下标越界:C语言数组索引从0开始,你申请了长度为8的内存空间,合法访问下标范围为0~7,代码中从buf[1]开始访问到buf[8],buf[8]属于越界访问非法内存,会读取到不可预期的垃圾值。
- 文件打开模式错误:使用
"r"文本模式打开PNG二进制文件,Windows系统下文本模式会自动对换行符做转义处理,篡改原始二进制字节内容,读取二进制文件必须使用"rb"二进制模式。 - 语法错误:所有
printf语句的格式字符串缺失左双引号,属于编译期语法错误,会导致实际运行逻辑不符合预期。 - 输出格式错误:PNG签名前几个字节属于非可打印ASCII字符,使用
%c输出会显示为乱码符号,无法和规范的十进制/十六进制值做比对。
修复方案
- 调整数组索引范围为0~7,访问
buf[0]到buf[7] - 将
fopen的打开模式改为"rb" - 补全所有
printf语句缺失的左双引号 - 将输出格式改为
%02X输出十六进制,或者%d输出十进制,方便和规范值比对 - 额外新增读取长度校验,避免读取过小的非PNG文件
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #define MAX_SIZE 8 int main(int argc, char **argv){ if(argc != 2) { printf("Usage: %s <png file>\n", argv[0]); return 1; } unsigned char *buf = (unsigned char *)malloc(MAX_SIZE); if(!buf) { fprintf(stderr, "Couldn't allocate memory\n"); return 1; } FILE *f = fopen(argv[1], "rb"); if(!f) { perror("fopen"); free(buf); return 1; } int size = fread(buf, 1, MAX_SIZE, f); if(size != MAX_SIZE) { fprintf(stderr, "File is too small to be a PNG\n"); fclose(f); free(buf); return 1; } // 输出十六进制签名 printf("PNG signature hex: "); for(int i=0; i<MAX_SIZE; i++) { printf("%02X ", buf[i]); } printf("\n"); // 输出十进制签名 printf("PNG signature dec: "); for(int i=0; i<MAX_SIZE; i++) { printf("%d ", buf[i]); } printf("\n"); fclose(f); free(buf); system("pause"); return 0; }
修复后运行正常会输出如下结果,和PNG规范完全一致:
PNG signature hex: 89 50 4E 47 0D 0A 1A 0A PNG signature dec: 137 80 78 71 13 10 26 10
内容的提问来源于stack exchange,提问作者NULL
相关产品推荐
相关产品推荐

