0

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?

1

The problem is here:

if (isalpha(argv[1]))

isalpha() takes a single char as input. argv[1] is a string. When you try to stuff a string into isalpha(), it chokes and seg faults.

If this answers your question, please click on the check mark to accept. Let's keep up on forum maintenance. ;-)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .