JChristen JChristen - 3 months ago 29
C Question

Valgrind possibly lost message when checking for memory leaks - C

I'm doing a course at the moment and one task is to create a program to resize 24 bit bitmap images by modifying some code they provide (which simply copies an image). The resizing itself was not a problem, but when I run a memory leak check with Valgrind I keep getting the message below. I can't for the life of me figure out where I'm going wrong and would appreciate some pointers (pun definitely intended) as to where the leak is, but nothing more.

Also, if you could let me know how good my code is, or ways I could improve at programming in general it would be greatly appreciated.

Valgrind message

Here's my code:

#include <stdio.h>
#include <stdlib.h>

#include "bmp.h"

int main(int argc, char* argv[])
{
// ensure proper usage
if (argc != 4)
{
printf("Usage: ./copy n infile outfile\n");
return 1;
}

// remember factor and filenames
int n = atoi(argv[1]);
char* infile = argv[2];
char* outfile = argv[3];

// check if scale factor is valid (i.e. between 1 and 100)
if ((n < 1) || (n > 100))
{
printf("Invalid scale factor, enter value between 1 and 100 inclusive\n");
return 2;
}

// open input file
FILE* inptr = fopen(infile, "r");
if (inptr == NULL)
{
printf("Could not open %s.\n", infile);
return 3;
}

// open output file
FILE* outptr = fopen(outfile, "w");
if (outptr == NULL)
{
fclose(inptr);
fprintf(stderr, "Could not create %s.\n", outfile);
return 4;
}

// read infile's BITMAPFILEHEADER
BITMAPFILEHEADER bf;
fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);

// read infile's BITMAPINFOHEADER
BITMAPINFOHEADER bi;
fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr);

// create headers for outfile
BITMAPFILEHEADER bfout = bf;
BITMAPINFOHEADER biout = bi;

// change output's header info w.r.t. n, the scale factor
biout.biWidth *= n;
biout.biHeight *= n;
biout.biSizeImage *= n * n;
bfout.bfSize = sizeof(BITMAPFILEHEADER) +
sizeof(BITMAPINFOHEADER) +
biout.biSizeImage;

// 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 5;
}

// write outfile's BITMAPFILEHEADER
fwrite(&bfout, sizeof(BITMAPFILEHEADER), 1, outptr);

// write outfile's BITMAPINFOHEADER
fwrite(&biout, sizeof(BITMAPINFOHEADER), 1, outptr);

// determine padding for scanlines
int paddingIn = (4 - (bi.biWidth * sizeof(RGBTRIPLE) % 4)) % 4;
int paddingOut = (4 - (biout.biWidth * sizeof(RGBTRIPLE) % 4)) % 4;

// iterate over infile's scanlines
for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
{
//create buffer and set to row's pixels
RGBTRIPLE* buffer = malloc(bi.biWidth * sizeof(RGBTRIPLE));
fread(buffer, sizeof(RGBTRIPLE), bi.biWidth, inptr);

// for each infile scanline, copy n times
for (int j = 0; j < n; j++)
{
// iterate over pixels in scanline
for (int k = 0; k < bi.biWidth; k++)
{
// copy pixel n times
for (int l = 0; l < n; l++)
fwrite(&buffer[k], sizeof(RGBTRIPLE), 1, outptr);

}

// then add padding to Outfile (if needed)
for (int k = 0; k < paddingOut; k++)
fputc(0x00, outptr);

}

// move past padding on infile
fseek(inptr, paddingIn, SEEK_CUR);

// free the buffer
free(buffer);
}

// close infile
fclose(inptr);

// close outfile
fclose(outptr);

// that's all, folks
return 0;
}

mch mch
Answer

You are analysing resize, which is a binary executable on your system.

If you call a program without ./ in front of it, the shell will search for a program with this name in every directory which is entered in the PATH variable (echo $PATH to see it), but not in the current directory.

You have to call your program with ./resize, so it will look in the . directory (your current directory) and will start your program.

The output Usage: resize [-u] [-c] [-s [rows cols]] does not match your code.