Mr.*_*Doe 2 c pointers file cs50
我正在使用一个 C 程序,该程序从单个文件中读取并用于sprintf将该数据写入多个文件,我在某处出错了,但我真的不知道哪里会导致此错误:
*** 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);
}
Run Code Online (Sandbox Code Playgroud)
我用我的调试器(CS50 调试器)对代码进行了分析。我发现这种if情况甚至从未被检查过。它从while循环跳转到else if条件,从不做任何事情,然后带着错误离开。
除了char * filename;应该是一个数组char filename[64];的问题,例如,这里有一个问题:
(array[3] & 0xf0==0)
Run Code Online (Sandbox Code Playgroud)
那是怎么评价的?
是((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);
^^^^^^^^^^^^^^
}
Run Code Online (Sandbox Code Playgroud)
编辑:另请注意,sizeof(char)正如@Jabberwocky 在评论中所注意到的那样,这应该是或只是 1(因为 sizeof(char) 始终是 1)。
顺便说一句:小心,sprintf因为它可能会溢出目标缓冲区。考虑snprintf改用。