0

I am a beginner learning C. From what I've learned and read here for example, you use malloc() when you don't know the amount of memory required at compile time. I am writing code in which I know the length of the string I am declaring but I get an error if I don't use malloc() to allocate it memory and I don't understand why.

The code I am writing is for a Harvard CS50 problem set in which the goal is to recover deleted jpgs but I've stripped it down to show just this problem. My code shows two lines declaring char* filename with the one that causes the error commented out. Both options compile, the one without malloc() causes a UndefinedBehaviorSanitizer:DEADLYSIGNAL error at run-time.

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

typedef uint8_t  BYTE;


int main(int argc, char *argv[])
{

    // remember filenames
    char *infile = argv[1];

    //open input file
    FILE *inptr = fopen(infile, "r");


    //buffer
    BYTE buffer[512];


    //read first 512 byte block in to buffer
    size_t r = fread(&buffer, 1, 512, inptr);

    int n = 0;
    //get name for new jpg file
    //char *filename[8]; //<<<<<<<<<<<<<<<<<<<<<this causes error
    char *filename = malloc(8);
    sprintf(filename, "%03i.jpg", n);

}

Here's the error:

UndefinedBehaviorSanitizer:DEADLYSIGNAL
==5563==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7fb433fba0ac bp 0x000000000030 sp 0x7ffd5af8a290 T5563)
==5563==The signal is caused by a WRITE memory access.
==5563==Hint: address points to the zero page.
    #0 0x7fb433fba0ab  (/lib/x86_64-linux-gnu/libc.so.6+0x900ab)
    #1 0x7fb433fb8493  (/lib/x86_64-linux-gnu/libc.so.6+0x8e493)
    #2 0x7fb433faa37d  (/lib/x86_64-linux-gnu/libc.so.6+0x8037d)
    #3 0x7fb433f86f1f  (/lib/x86_64-linux-gnu/libc.so.6+0x5cf1f)
    #4 0x7fb433fab6d0  (/lib/x86_64-linux-gnu/libc.so.6+0x816d0)
    #5 0x7fb433f8f093  (/lib/x86_64-linux-gnu/libc.so.6+0x65093)
    #6 0x428049  (/home/ubuntu/pset3/recover/malloc+0x428049)
    #7 0x7fb433f4bb96  (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
    #8 0x402ad9  (/home/ubuntu/pset3/recover/malloc+0x402ad9)

UndefinedBehaviorSanitizer can not provide additional info.
==5563==ABORTING
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
bor999
  • 3
  • 1
  • 8
    `char *filename[8];` creates an array of 8 (uninitialized) pointers. You probably want `char filename[8];` – pmg Jul 14 '19 at 15:50
  • `char filename[8]` will create a character array of length 8 for you. – Ignatius Jul 14 '19 at 15:51
  • 3
    Note that when `n >= 1000` you will cause buffer overflow with `sprintf(filename, "%03i.jpg", n);` because you need space for the `'\0'` terminator – pmg Jul 14 '19 at 15:53
  • Thanks pmg and Taegyung. char filename[8] runs without the error. The problem is limited to 50 jpgs, so n won't get above 50. – bor999 Jul 14 '19 at 16:05
  • In any case, use sprintf, so the worst that can happen is a truncated filename (which won't be found) instead of stack corruption. – Matteo Italia Jul 14 '19 at 16:35
  • This would be a good spot for an `assert(0 <= n && n <= 50)` to check during testing if that really is true. – Neil Jul 14 '19 at 20:28

1 Answers1

0
char *filename[8];

Ok so we declare an array of 8 pointers to characters, don't initialize any pointers, and pass one to a sprintf target.

Your working code is

char *filename = malloc(8);

which clearly declares a single pointer and initializes it with a pointer to 8 bytes off the heap. Therefore, you want

char filename[8];

which declares an array of 8 characters.

Joshua
  • 40,822
  • 8
  • 72
  • 132