How to dynamically allocate memory to a 2D array that stores the pixels of a bmp file in C?

Asked

Viewed 43 times

0

I am trying to dynamically allocate a 2D array to store a bmp file with the following code:

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

int height, width; // variables for the image height and width

int** storeImage (FILE* fil) { // function that reads and stores the image in a matrix
    int** img;

    char* trash = malloc(255 * sizeof(char)); 

    fscanf (fil, "%s", trash);
    free(trash);
    fscanf (fil, "%d", &width);
    fscanf (fil, "%d", &height);

    img = malloc (height * sizeof(int*));
    for (int i = 0; i < height; i++) {
        img[i] = malloc (width * sizeof(int));
    }
    fscanf (fil, "%d", &img[0][0]);
    for (int i = 0; i < height; i++) { // for that fills the matrix img
        for (int j = 0; j < width; j++) {
            fscanf (fil, "%d", &img[i][j]);
        }
    }

    return img;

}

int main (void) {

    char* file_name = malloc(255 * sizeof(char));
    scanf("%[^\n]s", file_name);
    getc(stdin); // consumes the '\n' or '\r'

    FILE* fil = NULL;
    fil = fopen(file_name, "r");

    int** img = storeImage(fil); // pointer to the matrix that represents the image

    fclose(fil); 

    for (int i = 0; i < height; i++) { // for that prints the matrix img
        for (int j = 0; j < width; j++) {
            printf("%d ", img[i][j]);
        }
        printf("\n");
    }   

    for (int i = 0; i < height; i++) { 
        free(img[i]);
    }
    free (img);
    free (file_name);

    return 0;
}

The file I am reading has the following format:

P2
5 6
255
10 13 18 12 11 
11 10 17 10 19 
16 17 19 11 12 
18 18 17 16 17 
13 12 19 13 15 
16 10 11 19 14 

At first, the program works and prints what I want in the terminal. However, when I run it on Valgrind, I get a Segmentation fault (core dumped):

==8965== Syscall param openat(filename) points to uninitialised byte(s)
==8965==    at 0x4B0E0EE: open (in /usr/lib/libc-2.26.so)
==8965==    by 0x4AA0CE2: _IO_file_open (in /usr/lib/libc-2.26.so)
==8965==    by 0x4AA0EB1: _IO_file_fopen@@GLIBC_2.2.5 (in /usr/lib/libc-2.26.so)
==8965==    by 0x4A94715: __fopen_internal (in /usr/lib/libc-2.26.so)
==8965==    by 0x108AC5: main (in /home/aluno/Projetos/debug)
==8965==  Address 0x4dde040 is 0 bytes inside a block of size 255 alloc'd
==8965==    at 0x403077F: malloc (vg_replace_malloc.c:299)
==8965==    by 0x108A7F: main (in /home/aluno/Projetos/debug)
==8965== 
==8965== Invalid read of size 4
==8965==    at 0x4A91F4D: __isoc99_fscanf (in /usr/lib/libc-2.26.so)
==8965==    by 0x108930: storeImage (in /home/aluno/Projetos/debug)
==8965==    by 0x108AD5: main (in /home/aluno/Projetos/debug)
==8965==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==8965== 
==8965== 
==8965== Process terminating with default action of signal 11 (SIGSEGV): dumping 
core
==8965==  Access not within mapped region at address 0x0
==8965==    at 0x4A91F4D: __isoc99_fscanf (in /usr/lib/libc-2.26.so)
==8965==    by 0x108930: storeImage (in /home/aluno/Projetos/debug)
==8965==    by 0x108AD5: main (in /home/aluno/Projetos/debug)
==8965==  If you believe this happened as a result of a stack
==8965==  overflow in your program's main thread (unlikely but
==8965==  possible), you can try to increase the size of the
==8965==  main thread stack using the --main-stacksize= flag.
==8965==  The main thread stack size used in this run was 8388608.
==8965== 
==8965== HEAP SUMMARY:
==8965==     in use at exit: 510 bytes in 2 blocks
==8965==   total heap usage: 4 allocs, 2 frees, 2,086 bytes allocated
==8965== 
==8965== LEAK SUMMARY:
==8965==    definitely lost: 0 bytes in 0 blocks
==8965==    indirectly lost: 0 bytes in 0 blocks
==8965==      possibly lost: 0 bytes in 0 blocks
==8965==    still reachable: 510 bytes in 2 blocks
==8965==         suppressed: 0 bytes in 0 blocks
==8965== Reachable blocks (those to which a pointer was found) are not shown.
==8965== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==8965== 
==8965== For counts of detected and suppressed errors, rerun with: -v
==8965== Use --track-origins=yes to see where uninitialised values come from
==8965== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)

What is the reason for this error?

1 answer

0

I did not touch the program, although it can be improved to be less confused, but here "on my machine" is not giving mistakes.

[~/Projects/testes/so]
$./390391
390391.dat
10 13 18 12 11 
11 10 17 10 19 
16 17 19 11 12 
18 18 17 16 17 
13 12 19 13 15 
16 10 11 19 14 

[~/Projects/testes/so]
$valgrind
valgrind: no program specified
valgrind: Use --help for more information.

[~/Projects/testes/so]
$valgrind ./390391
==11056== Memcheck, a memory error detector
==11056== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==11056== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==11056== Command: ./390391
==11056== 
390391.dat
10 13 18 12 11 
11 10 17 10 19 
16 17 19 11 12 
18 18 17 16 17 
13 12 19 13 15 
16 10 11 19 14 
==11056== 
==11056== HEAP SUMMARY:
==11056==     in use at exit: 0 bytes in 0 blocks
==11056==   total heap usage: 13 allocs, 13 frees, 7,374 bytes allocated
==11056== 
==11056== All heap blocks were freed -- no leaks are possible
==11056== 
==11056== For lists of detected and suppressed errors, rerun with: -s
==11056== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
  • How is that possible? on my machine I always get that same mistake

  • And how can I improve the code to make it less confusing?

  • I also can’t reproduce your problem. Which version of Valgrind are you using? Another possibility is to use the -fsanitize=memory flag in the build of the program to make it insert memory addressing checks.

  • @Mrparrot I’m using 3.14.0

Browser other questions tagged

You are not signed in. Login or sign up in order to post.