0

In the below code, if I add the last printf line, I get a heap-buffer-overflow error. Why does this happen? And how can I print the stuff saved in a2?

char ***a2 = (char***)malloc(10 * sizeof(char**));
char **a1 = (char**)malloc(10 * sizeof(char*));
a1[0] = (char*)malloc(10 * sizeof(char));
memset(a1[0], '#', 10);
a1[1] = (char*)malloc(10 * sizeof(char));
memset(a1[1], '=', 10);
a2[0] = a1;
printf("%s", a2[0][0]);  <---- error
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
Milo
  • 45
  • 1
  • 6

2 Answers2

3

You never zero-terminate the array of char so you can't use it as a string in a printf.

Instead of:

memset(a1[0], '#', 10);

Try:

memset(a1[0], '#', 9);  // Only memset the first 9 out of the 10 chars
a1[0][9] = '\0';        // Set the 10th char to be a string zero termination
Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
1

The strings you allocate for a1[0] and a1[1] (each of which has space for 10 characters) are then being filled with 10 copies of either '#' or '=' ... which means that neither has an explicitly-set (and required) nul terminator. Thus, the printf call causes undefined behaviour.

To fix this, you can use the calloc function to explicitly initialize the memory to zero, then only set one less than the buffer size copies of the character required (either by reducing this to 9 or increasing the allocation to 11):

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

int main()
{
    char*** a2 = malloc(10 * sizeof(char**));
    char** a1 = malloc(10 * sizeof(char*));

    a1[0] = calloc(10, sizeof(char)); // Sets all characters in buffer to 'nul'
    memset(a1[0], '#', 9);            // This leaves the last ('nul') intact!

    a1[1] = calloc(10, sizeof(char));
    memset(a1[1], '=', 9);

    a2[0] = a1;
    printf("%s", a2[0][0]);

    // Don't forget to free the memory you have allocated ...
    free(a1[0]);
    free(a1[1]);
    free(a1);
    free(a2);

    return 0;
}

Also, you might like to read: Do I cast the result of malloc?

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83