my resize compiles, but gives a segmentation fault immediately when run. I've worked on updating the file headers, I have yet to proceed to writing the bytes for the pixels.
When running GDB line by line from the beginning of main, the program returns when checking if argv[1] is numerical.
/**
* resize.c
*
* Computer Science 50
* Problem Set 4
*
* Resizes a BMP piece by piece, just because.
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <ctype.h>
#include "bmp.h"
int main(int argc, char* argv[])
{
// ensure proper usage
if (argc != 4)
{
printf("Usage: ./rezise n infile outfile\n");
return 1;
}
if (isalpha(argv[1]))
{
printf("Non-numerical n. Usage: ./rezise n infile outfile\n");
return 2;
}
// remember multiplier, filenames
int n = atoi(argv[1]);
char* infile = argv[2];
char* outfile = argv[3];
if (n < 1 || n > 100)
{
printf("Usage: 0 < n < 100");
return 3;
}
// open input file
FILE* inptr = fopen(infile, "r");
if (inptr == NULL)
{
printf("Could not open %s.\n", infile);
return 4;
}
// open output file
FILE* outptr = fopen(outfile, "w");
if (outptr == NULL)
{
fclose(inptr);
fprintf(stderr, "Could not create %s.\n", outfile);
return 5;
}
// read infile's BITMAPFILEHEADER
BITMAPFILEHEADER bf;
fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);
// read infile's BITMAPINFOHEADER
BITMAPINFOHEADER bi;
fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr);
// ensure infile is (likely) a 24-bit uncompressed BMP 4.0
if (bf.bfType != 0x4d42 || bf.bfOffBits != 54 || bi.biSize != 40 ||
bi.biBitCount != 24 || bi.biCompression != 0)
{
fclose(outptr);
fclose(inptr);
fprintf(stderr, "Unsupported file format.\n");
return 6;
}
// copy and update outfiles's BITMAPFILEHEADER values
BITMAPFILEHEADER bf_Out;
// copy and update outfiles's BITMAPINFOHEADER values
BITMAPINFOHEADER bi_Out;
// update bi_Out values
bi_Out.biWidth = n * bi.biWidth;
bi_Out.biHeight = n * bi.biHeight;
// determine padding for scanlines
int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
int out_padding = (4 - (bi_Out.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
// update bi_Out.biSizeImage according to padding
bi_Out.biSizeImage = sizeof((bi_Out.biWidth + out_padding) * bi_Out.biHeight);
// update bf_Out.bfSize
bf_Out.bfSize = bi_Out.biSizeImage + bf.bfOffBits;
// write outfile's BITMAPINFOHEADER
fwrite(&bi_Out, sizeof(BITMAPINFOHEADER), 1, outptr);
// write outfile's BITMAPFILEHEADER
fwrite(&bf_Out, sizeof(BITMAPFILEHEADER), 1, outptr);
// iterate over infile's scanlines
for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
{
// iterate over pixels in scanline
for (int j = 0; j < bi.biWidth; j++)
{
// temporary storage
RGBTRIPLE triple;
// read RGB triple from infile
fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
// write RGB triple to outfile
fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
}
// skip over padding, if any
fseek(inptr, padding, SEEK_CUR);
// then add it back (to demonstrate how)
for (int k = 0; k < padding; k++)
{
fputc(0x00, outptr);
}
}
// close infile
fclose(inptr);
// close outfile
fclose(outptr);
// that's all folks
return 0;
}
This is the output from GDB
Breakpoint 1, main (argc=4, argv=0x7fffffffdef8) at resize.c:20
20 if (argc != 4)
(gdb) n
26 if (isalpha(argv[1]))
(gdb) n
28 printf("Non-numerical n. Usage: ./rezise n infile outfile\n");
(gdb) info locals
n = 0
infile = 0x400e20 <__libc_csu_init> "AWA\211\377AVI\211\366AUI\211\325ATL\215%\310\017 "
outfile = 0x0
inptr = 0x7fffffffde10
outptr = 0x400e6d <__libc_csu_init+77>
bf = {bfType = 0, bfSize = 0, bfReserved1 = 0, bfReserved2 = 1, bfOffBits = 0}
bi = {biSize = 4294967295, biWidth = 0, biHeight = -8416, biPlanes = 32767, biBitCount = 0, biCompression = 4151439784, biSizeImage = 32767, biXPelsPerMeter = -134252016, biYPelsPerMeter = 32767, biClrUsed = 4160741832, biClrImportant = 32767}
bf_Out = {bfType = 20014, bfSize = 63037, bfReserved1 = 0, bfReserved2 = 1322, bfOffBits = 64}
bi_Out = {biSize = 0, biWidth = 0, biHeight = 0, biPlanes = 0, biBitCount = 0, biCompression = 4160742688, biSizeImage = 32767, biXPelsPerMeter = -8784, biYPelsPerMeter = 32767, biClrUsed = 4294958496, biClrImportant = 32767}
padding = 0
out_padding = 0
(gdb) n
Non-numerical n. Usage: ./rezise n infile outfile
29 return 2;
(gdb) n
140 }
(gdb) n
__libc_start_main (main=0x400900 <main>, argc=4, argv=0x7fffffffdef8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>,
stack_end=0x7fffffffdee8) at libc-start.c:321
321 libc-start.c: No such file or directory.
(gdb)
What could be causing the segmentation fault? Why is argv[1] tripping the if condition if it is numerical? Why does GDB show that the program returns when running it shows a segmentation fault?