c - (已解决)有人可以解释为什么 fread() 不起作用吗?
问题描述
经过几个小时的 cs50 恢复练习后,我遇到了分段错误问题。运行调试器后,我发现分段错误的原因是 的故障fread(memory, 512, 1, file)
,即使在调用该函数后,memory[]
数组仍然为空,因此,分段错误。
我尝试使用malloc(512)
而不是 unsigned char 数组,但错误仍然存在。有人可以解释为什么会发生这种情况以及如何解决吗?
(PS。对不起我的英语不好)
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(int argc, char *argv[])
{
// making sure the only user input is the name of the file
if (argc != 2)
{
printf("Usage: ./recover image\n");
return 1;
}
// open the file and check if it works
FILE *file = fopen("card.raw", "r");
if (file == NULL)
{
printf("Could not open card.raw.\n");
return 2;
}
int ending = 1000;
int count = 0;
char img = '\0';
FILE *picture = NULL;
unsigned char memory[512];
do
{
//creating buffer and reading the file into the buffer
fread(memory, 512, 1, file);
//checking if the block is a new jpg file
if (memory[0] == 0xff && memory[1] == 0xd8 && memory[2] == 0xff && (memory[3] & 0xf0) == 0xe0)
{
//if it's the first jpg file
if (count == 0)
{
sprintf(&img, "000.jpg");
picture = fopen(&img, "w");
fwrite(&memory, 512, 1, picture);
}
//closing previous jpg file and writing into a new one
else
{
fclose(picture);
img = '\0';
sprintf(&img, "%03i.jpg", count + 1);
picture = fopen(&img, "w");
fwrite(&memory, 512, 1, picture);
}
}
//continue writing into the file
else
{
picture = fopen(&img, "a");
fwrite(&memory, 512, 1, picture);
}
count++;
}
while(ending >= 512);
fclose(file);
fclose(picture);
return 0;
}
解决方案
如果您使用的是 C 或 C++,那么您应该充分了解所使用的内存模型。例如,声明一个字符局部变量,意味着在堆栈中分配 1 到 4 个字节的内存,具体取决于所使用的内存对齐和体系结构(16 位?32 位?64 位?)。猜猜当你对这样的字符局部变量执行超过 4 个字符的 sprintf 时会发生什么。它将溢出到占据 img 变量之后空间的任何变量。因此,您必须准备一个足够大的缓冲区来保存创建文件名所需的字符。在 C 语言中,如果你犯了错误,有几种可能性:
- 有时你在犯错后会出现分段错误
- 有时您没有收到任何错误,但数据已悄然损坏
- 有时在错误完成后很久就会发生错误
您的代码还有其他问题,Weather Vane 和 Jabberwocky 在上面的评论中已经指出了这一点。我想补充一点,重新打开'img'文件并丢弃以前的文件句柄也不是一件好事(你已经说过继续写?为什么需要重新打开?)。您可能会得到一个悬空的文件句柄或在迭代期间不必要地创建许多文件句柄。C 不会帮你检查这些东西,它假设你真的知道你在做什么。即使混合类型也不会导致编译错误或可识别的运行时错误。它只会做我上面所说的三件事之一。
您可能想使用其他具有更多内存安全功能的现代语言来学习编程,例如 C#、Java 或 Python。
推荐阅读
- c# - 我在 azure 中部署的 Web 应用程序需要指向一个静态 IP 地址
- tsql - 使用 T-SQL 在具有多数据的单个脚本中将数据插入到 Master 和 Detail 表
- db2 - SQL1092N 请求的命令或操作失败,因为用户标识没有执行请求的命令或操作的权限
- ios - 需要帮助完成我在状态机上的第一次测试计时器应用程序尝试 - 我想我仍然有转换错误
- reactjs - 在没有 ES6 或 Webpack 的情况下使用 CDN 链接反应 redux
- node.js - 当回调未作为参数传递时,如何使用 sinon 在 node.js 中对回调进行单元测试?
- automation - QTP 11 与 Flex 3.0
- java - 'ol 错误:无法找到或加载主类 os x
- php - FETCH_ASSOC 仅显示 1 个数据和循环无限 PHP
- gammu - 打开设备时出错,您没有权限(gammu 安装后)