【问题标题】:Valgrind possibly lost message when checking for memory leaks - CValgrind 在检查内存泄漏时可能会丢失消息 - C
【发布时间】:2015-10-23 14:15:22
【问题描述】:

我现在正在做一门课程,其中一项任务是创建一个程序,通过修改它们提供的一些代码(它只是复制图像)来调整 24 位图图像的大小。调整大小本身不是问题,但是当我使用 Valgrind 运行内存泄漏检查时,我不断收到以下消息。我一生都无法弄清楚我哪里出错了,我希望能得到一些关于泄漏位置的指示(绝对是双关语),但仅此而已。

另外,如果您能告诉我我的代码有多好,或者我可以在总体上改进编程的方法,我们将不胜感激。

这是我的代码:

#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;
}

【问题讨论】:

  • 你能告诉我们你用什么参数来编译你的代码吗?
  • @jayant 如果你打算复制,你还需要“bmp.h”
  • @Kotshi 在这个阶段我只想确保代码是用调试符号编译的-g
  • 你应该用./resize调用你的程序,否则你会从你的linux系统调用resize
  • @mch 您应该在找到解决方案时使用答案。

标签: c memory-leaks valgrind bmp


【解决方案1】:

您正在分析resize,它是您系统上的二进制可执行文件。

如果你调用一个前面没有./的程序,shell会在PATH变量(echo $PATH查看)中输入的每个目录中搜索具有此名称的程序,但不会在当前目录中。

您必须使用./resize 调用您的程序,因此它会在. 目录(您的当前目录)中查找并启动您的程序。

输出Usage: resize [-u] [-c] [-s [rows cols]] 与您的代码不匹配。

【讨论】:

  • 吹毛求疵:虽然通常通过 shell 调用,resize 不是 shell 命令,而是一个简单的二进制可执行文件。
  • @alk 谢谢,我已经添加了一些信息。我不知道resize是什么,它也可能是一个脚本文件。
  • 谢谢@mch!完美运行,没有内存泄漏!
猜你喜欢
  • 1970-01-01
  • 2017-08-13
  • 1970-01-01
  • 2016-08-08
  • 2013-01-26
  • 1970-01-01
  • 2020-03-31
  • 2016-03-15
  • 1970-01-01
相关资源
最近更新 更多