sprintf 和 fwrite() 的分段错误;程序仅适用于 valgrind
Segmentation Fault with sprintf and fwrite(); program only works with valgrind
我在 运行 运行我的程序时遇到分段错误,该程序只允许我打印出 1 个损坏的图像。但是,当我 运行 使用 valgrind 的程序时,它打印出 50 张照片中的 49 张照片,唯一不工作的照片是最后一张。
在 运行对程序进行 help50 valgrind 后,我意识到 sprintf 存在分段错误,并且在程序末尾的 fwrite() 可能存在问题。如有任何澄清,我们将不胜感激。
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main(int argc, char *argv[])
{
// Check you're actually recovering a file.
if (argc != 2)
{
printf("Invalid entry.\n");
return 0;
}
// Open file for reading.
FILE *file = fopen(argv[1], "r");
if (!file)
{
return 1;
}
// Set 1st photo as jpg.001.
int counter = 1;
// Check if bytes are jpg. signatures.
for (int n = 0; counter < 51; n = n + 512)
{
// Sets an array to contain 4 values and directs pointer to start from nth value each time.
unsigned char array[512];
fseek(file, n, SEEK_SET);
fread(array, 1, 512, file); // if EOF, won't have 512 to write into!!!
// Declare character array jpg.
char* jpg_name;
// While 1st 4 bytes are jpg signature.
if (array[0] == 0xff && array[1] == 0xd8 && array[2] == 0xff && (array[3] & 0xf0) == 0xe0)
{
// Convert integer to string and store into jpg character array. Increment image number.
jpg_name = malloc(4*sizeof(char));
sprintf(jpg_name, "%03i.jpg", counter);
counter++;
// Open images file to write into,allocate memory to jpg file to write into, write 512 bytes from array into image file.
FILE *images = fopen(jpg_name, "a");
fwrite(array, 1, 512, images);
// Free file memory?
free(jpg_name);
fclose(images);
}
else // If 1st 4 bytes aren't jpg signature.
{
// Add bytes to existing image (if present), otherwise repeat loop.
if (counter > 1)
{
FILE *images = fopen(jpg_name, "a");
fwrite(array, 1, 512, images); // SEGMENTATION FAULT; need to detect end of file.
fclose(images);
}
else
{
continue;
}
}
}
}
警告:没有您的输入文件,我无法完全测试这个提议的代码。
警告:提议的代码要求输入文件的第一行包含第一个 .jpg 图像的 'header'
警告:提议的代码要求每张图像都是 512 字节的倍数
建议代码如下:
- 干净地编译
- 执行所需的功能(就测试而言)
- 正确检查 I/O 错误
- 以二进制模式正确打开文件(尽管 Linux 不关心)
- 假设每个图像都是 512 字节的倍数
- 正确区分错误退出和成功退出
- 不包含头文件那些内容没有用到
现在,建议的代码:
#include <stdio.h>
#include <stdlib.h>
// #include <stdbool.h>
int main(int argc, char *argv[])
{
// Check the user entered a command line parameter for a input file name
if (argc != 2)
{
fprintf( stderr, "USAGE: %s inputFileName\n", argv[0] );
exit( EXIT_FAILURE );
}
// Open file for reading.
FILE *file = fopen(argv[1], "rb");
if (!file)
{
perror( "fopen for input file failed");
exit( EXIT_FAILURE );
}
// Set 1st photo as jpg.001.
// Declare character array jpg.
char jpg_name[10];
FILE *images = NULL;
for (int counter = 0; counter < 51; )
{
unsigned char array[512];
ssize_t bytesRead;
if( (bytesRead = fread(array, 1, 512, file) != 512 ) )
{
perror( "fread failed" );
fclose( images );
fclose( file );
exit( EXIT_FAILURE );
}
// if 1st 4 bytes are jpg signature.
if ( array[0] == 0xff
&& array[1] == 0xd8
&& array[2] == 0xff
&& (array[3] & 0xf0) == 0xe0)
{
if( images )
{
fclose( images );
images = NULL;
counter++;
}
sprintf(jpg_name, "%03i.jpg", counter+1);
images = fopen(jpg_name, "wb");
if( ! images )
{
perror( "fopen for output file failed" );
fclose( file );
exit( EXIT_FAILURE );
}
}
// Add bytes to current output image
if( fwrite(array, 1, 512, images) != 512 )
{
perror( "fwrite failed" );
fclose( images );
fclose( file );
exit( EXIT_FAILURE );
}
}
fclose( images );
fclose( file );
}
我在 运行 运行我的程序时遇到分段错误,该程序只允许我打印出 1 个损坏的图像。但是,当我 运行 使用 valgrind 的程序时,它打印出 50 张照片中的 49 张照片,唯一不工作的照片是最后一张。
在 运行对程序进行 help50 valgrind 后,我意识到 sprintf 存在分段错误,并且在程序末尾的 fwrite() 可能存在问题。如有任何澄清,我们将不胜感激。
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main(int argc, char *argv[])
{
// Check you're actually recovering a file.
if (argc != 2)
{
printf("Invalid entry.\n");
return 0;
}
// Open file for reading.
FILE *file = fopen(argv[1], "r");
if (!file)
{
return 1;
}
// Set 1st photo as jpg.001.
int counter = 1;
// Check if bytes are jpg. signatures.
for (int n = 0; counter < 51; n = n + 512)
{
// Sets an array to contain 4 values and directs pointer to start from nth value each time.
unsigned char array[512];
fseek(file, n, SEEK_SET);
fread(array, 1, 512, file); // if EOF, won't have 512 to write into!!!
// Declare character array jpg.
char* jpg_name;
// While 1st 4 bytes are jpg signature.
if (array[0] == 0xff && array[1] == 0xd8 && array[2] == 0xff && (array[3] & 0xf0) == 0xe0)
{
// Convert integer to string and store into jpg character array. Increment image number.
jpg_name = malloc(4*sizeof(char));
sprintf(jpg_name, "%03i.jpg", counter);
counter++;
// Open images file to write into,allocate memory to jpg file to write into, write 512 bytes from array into image file.
FILE *images = fopen(jpg_name, "a");
fwrite(array, 1, 512, images);
// Free file memory?
free(jpg_name);
fclose(images);
}
else // If 1st 4 bytes aren't jpg signature.
{
// Add bytes to existing image (if present), otherwise repeat loop.
if (counter > 1)
{
FILE *images = fopen(jpg_name, "a");
fwrite(array, 1, 512, images); // SEGMENTATION FAULT; need to detect end of file.
fclose(images);
}
else
{
continue;
}
}
}
}
警告:没有您的输入文件,我无法完全测试这个提议的代码。
警告:提议的代码要求输入文件的第一行包含第一个 .jpg 图像的 'header'
警告:提议的代码要求每张图像都是 512 字节的倍数
建议代码如下:
- 干净地编译
- 执行所需的功能(就测试而言)
- 正确检查 I/O 错误
- 以二进制模式正确打开文件(尽管 Linux 不关心)
- 假设每个图像都是 512 字节的倍数
- 正确区分错误退出和成功退出
- 不包含头文件那些内容没有用到
现在,建议的代码:
#include <stdio.h>
#include <stdlib.h>
// #include <stdbool.h>
int main(int argc, char *argv[])
{
// Check the user entered a command line parameter for a input file name
if (argc != 2)
{
fprintf( stderr, "USAGE: %s inputFileName\n", argv[0] );
exit( EXIT_FAILURE );
}
// Open file for reading.
FILE *file = fopen(argv[1], "rb");
if (!file)
{
perror( "fopen for input file failed");
exit( EXIT_FAILURE );
}
// Set 1st photo as jpg.001.
// Declare character array jpg.
char jpg_name[10];
FILE *images = NULL;
for (int counter = 0; counter < 51; )
{
unsigned char array[512];
ssize_t bytesRead;
if( (bytesRead = fread(array, 1, 512, file) != 512 ) )
{
perror( "fread failed" );
fclose( images );
fclose( file );
exit( EXIT_FAILURE );
}
// if 1st 4 bytes are jpg signature.
if ( array[0] == 0xff
&& array[1] == 0xd8
&& array[2] == 0xff
&& (array[3] & 0xf0) == 0xe0)
{
if( images )
{
fclose( images );
images = NULL;
counter++;
}
sprintf(jpg_name, "%03i.jpg", counter+1);
images = fopen(jpg_name, "wb");
if( ! images )
{
perror( "fopen for output file failed" );
fclose( file );
exit( EXIT_FAILURE );
}
}
// Add bytes to current output image
if( fwrite(array, 1, 512, images) != 512 )
{
perror( "fwrite failed" );
fclose( images );
fclose( file );
exit( EXIT_FAILURE );
}
}
fclose( images );
fclose( file );
}