[英]“*** stack smashing detected ***” with file read and writes
我正在使用从单个文件读取并使用sprintf
将该数据写入多个文件的 C 程序,我在某个地方出错了,但我真的不知道哪里会导致此错误:
*** stack smashing detected ***
这里给出了可用于复制的代码:
FILE * source=fopen("card.raw","r");// defines source I will read from
char array[512];
int active_read=0;
char * filename;
sprintf(filename, "%03i.jpg",i);
FILE *image=fopen(filename, "a"); //my understanding of sprintf to create a file
while(fread(array,sizeof(char *),512,source)==512) // if 512 characters can be detected
{
if(array[0]==0xff && array[1]==0xd8 && array[2]==0xff && (array[3] & 0xf0==0))
{
if(active_read==1)
fclose(image);
active_read=1;
sprintf(filename, "%03i.jpg",i);
image=fopen(filename, "a");
fwrite(array, sizeof(char *),512, image);
i++;
}
else if(active_read==1)
fwrite(array, sizeof(char *), 512, image);
}
我用我的调试器(CS50 调试器)对代码进行了分析。 我发现if
条件甚至从未被检查过。 它从while
循环跳转到else if
条件,从不做任何事情,然后带着错误离开。
除了char * filename;
的问题char * filename;
那应该是一个数组,例如char filename[64];
,这里有一个问题:
(array[3] & 0xf0==0)
那是怎么评价的?
是((array[3] & 0xf0)==0)
还是(array[3] & (0xf0==0))
?
查看https://en.cppreference.com/w/c/language/operator_precedence ,您会看到==
优先级高于&
。 因此,您首先执行0xf0 == 0
。 这总是错误的(又名零)所以你的表达总是错误的。 所以编译器被允许(并且可能会)优化生成的代码,以便在运行时不计算表达式。 相反,它总是直接转到else if
部分。
换句话说 - 允许编译器将您的代码视为:
while(fread(array,sizeof(char *),512,source)==512)
{
if(active_read==1)
fwrite(array, sizeof(char *), 512, image);
^^^^^^^^^^^^^^
}
编辑:另请注意,正如@Jabberwocky 在评论中所注意到的,这应该是sizeof(char)
或只是 1(因为 sizeof(char) 始终为 1)。
顺便说一句:使用sprintf
要小心,因为它可能会溢出目标缓冲区。 考虑使用snprintf
代替。
要添加到@4386427 的答案中,如果您的char
类型已签名,则比较array[0]==0xff
将始终为假,如下所示(也是一个专业提示:尝试启用编译器提供的每个警告)。
原因是0xFF
是255
,它被提升为int
,然后与也被提升为 int 的有signed char
进行比较,但值的可能范围从 -128 到 127。
如果char
是signed
,要确保您的代码正常工作,请将array
声明更改为使用unsigned char
,或在比较之前强制转换为 unsigned :
if ( (unsigned char)array[0] == 0xff &&
(unsigned char)array[1] == 0xd8 &&
(unsigned char)array[2] == 0xff &&
((unsigned char)array[3] & 0xf0) == 0 )
...
所以它看起来像是我的 if 条件导致问题的一般概念:
if(array[0]==0xff && array[1]==0xd8 && array[2]==0xff)
因为我一直在将字符数组中的单个字符与一个字节进行比较。 我已经将array
的类型更改为BYTE *
并且问题解决了
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.