c - "*** stack smashing detected ***"带文件读写

标签 c file pointers cs50

我正在使用从单个文件读取并使用 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[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);
                      ^^^^^^^^^^^^^^
}

编辑:另请注意,这应该 是 sizeof(char) 或只是 1(因为 sizeof(char) 总是 1) 正如@Jabberwocky 在评论中指出的那样。

顺便说一句:小心 sprintf,因为它可能会溢出目标缓冲区。考虑改用 snprintf

关于c - "*** stack smashing detected ***"带文件读写,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63736352/

相关文章:

c - GPS UART数据多次写入Buffer

c - 这段代码是否使用 sizeof 运算符定义得很好?

c - Linux 中 chattr 的替代方法

c++ - 释放容器成员的内存

c++ - 在一行中删除多个指针。 C++

c - 两个进程共享内存中的结构体数组

c - 生成随机不同数字的数组

创建一个产生字符串的 FILE * 流

android - 如何在 Android 内部存储上创建文件?

c++ - 从指向其类成员之一的指针计算类的指针