Search code examples
cprintfmallocvalgrind

Malloc'd char array has unexpected output


My problem is simple, I don't understand why this program doesn't output correctly :

int size = 35;
// malloc size for text
char *txt = malloc(size * sizeof(char *));
if(!txt) {
    fprintf(stderr, "Allocation for text data failed.\n");
    return EXIT_FAILURE;
}

for(int i = 0; i < size; i++) { // for each character in text
    txt[i] = 'a';
}
printf("%s\n", txt);
free(txt);

Expected output :

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

Actual output :

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa8 9 10 1 0 12 11 6 37 44 3 45 56 0 64 77 5 68 83 0 39 46 0 19 16 9 8 2 6 3 1 4 17 12 9 17 6 0 25 10 3 31 16 13 21 9 9 11 7 4 2 3 0 7 6 1 9 5 2 11 2 5 19 6 13 21 8 15 8 0 0 7 0 0 29 20 13 62 50 0 49 35 0 41 27 1 38 25 9 25 13 0 21 11 0 24


Tried debugging with valgrind --leak-check=yes, the only error it shows is the following :

==3999== Conditional jump or move depends on uninitialised value(s)
==3999== at 0x4C30F78: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3999== by 0x4EA969B: puts (ioputs.c:35)
==3999== by 0x400B39: main (decode.c:85) // this is the printf line

I thought it was because it didn't know when to stop printing, but I tried :

while(txt != NULL) {
    printf("%c", *(txt++));
}

And I also tried :

txt[size - 1] = '\0';

while((*txt) != '\0') {
    printf("%c", *(txt++));
}

Those gave even worse results where it would fill my console with special characters.


Solution

  • Put the \0 in the char array. Otherwise printf will have undefined behavior.

    Also in malloc you are allocating for char not char*.

    Example

    int size = 35;
    // malloc size for text
    char *txt = malloc((size+1) * sizeof(char ));
    if(!txt) {
        fprintf(stderr, "Allocation for text data failed.\n");
        return EXIT_FAILURE;
    }
    memset(txt,0,size+1); 
    for(int i = 0; i < size; i++) { // for each character in text
        txt[i] = 'a';
    }
    
    printf("%s\n", txt);
    free(txt);
    txt=NULL;
    
    1. Alternatively one can set txt[size]='\0' also because all other position are overwritten with characters inputted. [Peter commented this]