繁体   English   中英

“***堆栈粉碎检测到***”文件读写

[英]“*** 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将始终为假,如下所示(也是一个专业提示:尝试启用编译器提供的每个警告)。

原因是0xFF255 ,它被提升为int ,然后与也被提升为 int 的有signed char进行比较,但值的可能范围从 -128 到 127。

如果charsigned ,要确保您的代码正常工作,请将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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM