#Why do I need to set the first byte of a malloced pointer to null?

37 messages · Page 1 of 1 (latest)

rancid mist
#

Hi! I have this:

    char authToken[] = "token";

    char *authHeader = malloc(
        (strlen("Authorization: Bearer ") + strlen(authToken)) * sizeof(char));
    // authHeader = '\0'; // if I uncomment this, the output will be as expected: Authorization: Bearer token
    strcat(authHeader, "Authorization: Bearer ");
    strcat(authHeader, authToken);
    printf("%s\n", authHeader);
    free(authHeader);

If I don't uncomment the given line, then the output looks something like this: r�j[�UAuthorization: Bearer token

Why is this? Am I doing something wrong with malloc? Also, am I doing anything unnecessary here? I feel like I am, but I'm really not quite sure.

wary tuskBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

tepid egret
#

malloc does not clear the allocated memory. Any data that was there previously is still there

#

So the new pointer points to data that already existed.
As strings are defined to end at the first '\0', you have to set the first byte to '\0' to have the string be considered empty

wooden saffron
#

and then strcat() looks for the first null byte to start copying in its string

#

so the "r�j[�U" is the random garbage that was in the random bit of memory you were given by malloc()

rancid mist
#

So there was already something in that memory, and then malloc() came along and "claimed" that section of memory. If I'm overwriting everything that I allocated with malloc() though, why are there any leftover bytes that aren't being used? Why wouldn't strcat() start at the first byte of allocated memory?

tepid egret
#

all strcat see is a pointer to what it thinks is a string.
Strings are defined to end at the first null character.
So it searchs the data for that null character to start adding data to

rancid mist
#

oh wait that just clicked, yeah, that makes sense, thank you!

tepid egret
#

hell yeh

rancid mist
#

Wait but wouldn't that take more memory than I allocated?

#

Lemme expand on that rq

tepid egret
#

strcat does not allocate any additional memory.
It expects the destination has enough space

#

Oh do you mean, you'll need extra space for the final null character?

rancid mist
#

But if I:

char *a = malloc(5 * sizeof(char));
strcat(a, "12345");

And strcat() doesn't find a null character until, say the 3rd byte, then haven't we used the memory equivalent to the length of the string + 3 (bytes)?

tepid egret
#

length of the string + 3 bytes + 1 byte for the final null character

#

There are two solutions:
Add a null character

char *a = malloc(6 * sizeof(char));
*a = 0;
strcat(a, "12345");

or use strcpy instead of strcat for the first function

char *a = malloc(6 * sizeof(char));
strcpy(a, "12345");
rancid mist
#

But what about the x characters before the null character? Wouldn't that be going through the space that we just malloc()ed, so we would only be left with 2 spare bytes to put a 5 byte string in?

tepid egret
#

so in solution 1, we are setting the first character to the null character, so there therw will be no character before the first null.
In the second solution, strcpy (string copy) copies the source to the destination direction

rancid mist
#

But if we didn't do that, it still works (it just includes a few pseduo-random characters before it)?

char *a = malloc(6 * sizeof(char));
strcat(a, "12345");
printf("%s\n", a); // ${;12345
tepid egret
#

oh, are you confused how the string is able to be longer than the allocated memory

#

one moment

rancid mist
#

yea, ty

wary tuskBOT
#

@rancid mist Has your question been resolved? If so, type !solved :)

tepid egret
#

So there are no boundary checking with memory in C. It sees all of memory as just a single block of data. Allocating memory is just asking politely for memory that won't be used by others, but it will not police how that memory is used.
Basically the 4 5 \0 might be stored in a part of memory used by some other variable or something

             not
           -------
$ { ; 1 2 3 4 5 \0
-----------
 allocated
#

;compile

int a[] = {1, 2, 3};
int b[] = {4, 5, 6};
b[4] = 9;

for (int i = 0; i < 3; ++i)
  printf("%d,", a[i]);
printf("\n");
for (int i = 0; i < 3; ++i)
  printf("%d,", b[i]);
obtuse ridgeBOT
#
Program Output
1,9,3,
4,5,6,
tepid egret
#

See how b[4] = 9; is overwriting a[1]

rancid mist
#

Ok, that does make a lot more sense now (thank you!). Would b[4] = 9; always overwrite a[1], or could it overwrite something else (semi-randomly?)

tepid egret
#

It is what is known as "undefined behaviour"
I would be hesitant to say "random" but it's more that the C standard (what defines the language) says stuff like 'If you do A, B, C, we can guarantee certain behaviour, otherwise there are no guarantees"

#

So b[4] = 9; will (pretty much) always overwrite what is ever 8 bytes (sizeof(int) * 2) ahead of b in memory, but there is no guarantee what will be there. You could in theory overwrite the return address and crash the program

rancid mist
#

ah ok, that make sense

#

thank you very much!

tepid egret
#

Basically, you can go past the bounds, but if you do, there is no promises on what can happen, so it is up to you to prevent that

rancid mist
#

duly noted, thanks again! gonna close this now

#

!solved

wary tuskBOT
#

Thank you and let us know if you have any more questions!

This thread is now set to auto-hide after an hour of inactivity