Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

String and pointers in C

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

int main(void)
{
        char* a = malloc(5 * sizeof(char));
        a = "1";
        free(a);
}

I have two questions regarding the above code:

  1. Why does the code gives an error with free(a) when I initialize a like this :

a = "1"

and doesn't give any error with free(a) when I initialize a like this :

a[0] = '1'.

  1. When I initialize a with a[0] = '1' and print the string a using printf("%s", a) why do I get the result

    '1'

without declaring the second index with a '\0'?
like image 892
Lokesh Avatar asked Dec 05 '22 05:12

Lokesh


1 Answers

The rules with malloc and free are that you must only pass to free a pointer that was allocated by a call to malloc (or one of its equivalents like realloc or calloc). You do not do that:

char* a = malloc(5 * sizeof(char));
a = "1";
free(a);

When you call free, you pass a which was not allocated by a call to malloc. This results in your program having undefined behaviour.


The problem in your understanding is that I suspect you don't understand what a = "1" does.

I suspect that you imagine this to copy the string in to the memory that you allocated it does not. It changes the pointer a to point to a different address.

Indeed, by assigning to a, rather than the memory that it points to, you are leaking the allocated memory. Your code is exactly analogous to this:

int i = 1;
i = 2;

I'm sure you can see that the initialization of i is pointless because you immediately overwrite the value of i with a new value. That's exactly what you did with your pointer.


You can copy the string with strcpy. Like this:

char* a = malloc(5 * sizeof(char));
strcpy(a, "1");
free(a);

Similarly, when you wrote

char* a = malloc(5 * sizeof(char));
a[0] = '1';
printf("%s", a);
free(a);

you were assigning the contents of the buffer allocated by your call to malloc. And hence the call to free is correct.

However, the string is not necessarily null-terminated when you do that. You observed that your printf appeared to work but that was just by chance.

The contents of a[1] are ill-defined and it seems that, by chance, a[1] did contain a null when you ran your program.

This is why you typically use a string function like strcpy to perform copies and ensure null-termination. You do of course need to take care not to overrun your buffer.


Finally, by definition, sizeof(char) == 1 so you can write the malloc like this:

char* a = malloc(5);
like image 166
David Heffernan Avatar answered Dec 11 '22 09:12

David Heffernan