我正在执行 cs50 任务,我需要从存储卡中恢复所有从卡复制到 card.raw 文件的 jpg 图像。下面是工作代码。但是如果我在数组下面声明一个计数变量,即 像这样
BYTE jpgBlock[512];
int count = 0;
程序停止正常工作。即,在while循环中,在第一次通过内循环后(找到签名jpg并将第1张图像写入末尾 - 即直到满足下一张图像的签名)结束时,计数器增加,计数为 1,行执行后转到 2 pass
sprintf(outfile, "%03d.jpg", count);
计数器被重置,即 计数变为 0。这是为什么?为什么要看count是声明在BYTE jpgBlock[512]之上还是之下?
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <cs50.h>
typedef uint8_t BYTE;
int main(void)
{
FILE *inptr = fopen("card.raw", "r");
if (inptr == NULL)
{
return 1;
}
int count = 0;
BYTE jpgBlock[512];
while(1)
{
char outfile[7];
sprintf(outfile, "%03d.jpg", count);
FILE *outptr = fopen(outfile, "w");
if(outptr == NULL)
{
return 2;
}
for (int countFirstBlock = 0; fread(jpgBlock, sizeof(jpgBlock), 1, inptr) == 1; )
{
if(jpgBlock[0] == 255 && jpgBlock[1] == 216 && jpgBlock[2] == 255)
{
++countFirstBlock;
}
if(countFirstBlock == 1)
{
fwrite(jpgBlock, sizeof(jpgBlock), 1, outptr);
}
if(countFirstBlock == 2)
{
break;
}
}
fclose(outptr);
if(feof(inptr))
{
break;
}
fseek(inptr, -(int)sizeof(jpgBlock), SEEK_CUR);
++count;
}
fclose(inptr);
return 0;
}
关键是你的
缓冲区溢出
并导致未定义的行为。特别是,这可以很容易地通过覆盖您的邻近记忆来表达
count。你
sprintf的形成一个至少 7 个字符长的字符串。要存储这样的字符串,需要一个大小为 8 的缓冲区,因为该字符串还必须包含空终止符。而且你只分配了一个大小为 7 的缓冲区。溢出是有保证的。