Why don't I have to use free() after allocating without malloc() - c

Everybody knows that you have to free() pointers, when you use malloc() because the memory is allocated in the heap, which is not kept account of by the process.
But why don't I have to use free() when assigning a pointer without a heap:
char* text0 = calloc(20, sizeof (char));
strncpy(text0, "Hello World", 20); // Remember to use `free()`!
char* text1 = "Goodbye World!"; // No need for `free()`?
Isn't text1 also a pointer on the stack pointing to the memory allocated on the heap? Why is there no need for free()?

The string constant "Goodbye World!" is placed in a global, read-only section of memory at program startup. It is not allocated on the heap. Same goes for "Hello World".
So after the assignment, text1 points to this static string. Since the string does not exist on the heap, there's no need to call free.

free must be used for all memory allocated with malloc. You allocate memory from the heap and must return it so you can use it later again.
char* text0 = calloc(20, sizeof(char)); // this memory must be freed.
In:
text0 = "Hello World";
you ovewrite the pointer to the allocated memory. The memory is now lost and cannot be reclaimed/reused again.
Note the parenthesis around char in sizeof(char) and note that I dropped the * before text0 as you are assigning the address of the constant string to a variable of type "pointer to character". Turn warnings on when compiling!
You should have done:
free(text0);
text0 = "Hello World"; // DON'T use `free()`!
Note again I dropped the *. More reasons to turn warnings on when compiling.
char* text1 = "Goodbye World!"; // No need for `free()`?
No, no need to call free because you did not allocate from the heap.

Related

Using malloc to initialize char pointer VS not using malloc and just assign a string directly to the char pointer

I'm trying to understand how this memory allocation thing works when it comes to char and strings.
I know that the name of a declared array is just like a pointer to the first element of the array, but that array will live in the stack of the memory.
On the other hand, we use malloc when we want to use the heap of the memory, but I found that you can just initialize a char pointer and assign a string to it on the very same declaration line, so I have some questions regarding this matter:
1) If I just initialize a char pointer and assign a string to it, where is this information living? In the heap? In the stack?
Ex: char *pointer = "Hello world";
2) I tried to use malloc to initialize my char pointer and use it later to assign a string to it, but I can't compile it, I get error, what is wrong with this logic? this is what I'm trying to do:
char *pointer = malloc(sizeof(char) * 12);
*pointer = "Hello world";
Can you please help me understand more about pointers and memory allocation? Thank you very much! :)
1) If I just initialize a char pointer and assign a string to it,
where is this information living? In the heap? In the stack? Ex: char
*pointer = "Hello world";
Neither on the stack or on the heap. "Hello world" is a string literal, generally created in the rodata (read-only data) segment of the executable. In fact, unless you specify differently, the compiler is free to only store a single copy of "Hello world" even if you assign it to multiple pointers. While typically you cannot assign strings to pointers, since this is a string literal, you are actually assigning the address for the literal itself -- which is the only reason that works. Otherwise, as P__J__ notes, you must copy strings from one location to another.
2) I tried to use malloc to initialize my char pointer and use it
later to assign a string to it, but I can't compile it, I get error,
what is wrong with this logic? this is what I'm trying to do:
char *pointer = malloc(sizeof(char) * 12);
*pointer = "Hello world";
You are mixing apples and oranges here. char *pointer = malloc (12); allocates storage for 12-characters (bytes) and then assigns the beginning address for that new block of storage to pointer as its value. (remember, a pointer is just a normal variable that holds the address to something else as its value)
For every allocation, there must be a validation that the call succeeded, or you will need to handle the failure. Allocation can, and does fail, and when it fails, malloc, calloc * realloc all return NULL. So each time you allocate, you
char *pointer = malloc(12); /* note: sizeof (char) is always 1 */
if (pointer == NULL) { /* you VALIDATE each allocation */
perror ("malloc-pointer");
return 1;
}
Continuing with your case above, you have allocated 12-bytes and assigned the starting address for the new memory block to pointer. Then, you inexplicably, derefernce pointer (e.g. *pointer which now has type char) and attempt to assign the address of the string literal as that character.
*pointer = "Hello world"; /* (invalid conversion between pointer and `char`) */
What you look like you want to do is to copy "Hello world" to the new block of memory held by pointer. To do so, since you already know "Hello world" is 12-characters (including the nul-terminating character), you can simply:
memcpy (pointer, "Hello world", 12);
(note: if you already have the length, there is no need to call strcpy and cause it to scan for the end-of-string, again)
Now your new allocated block of memory contains "Hello world", and the memory is mutable, so you can change any of the characters you like.
Since you have allocated the storage, it is up to you to free (pointer); when that memory is no longer in use.
That in a nutshell is the difference between assigning the address of a string literal to a pointer, or allocating storage and assigning the first address in the block of new storage to your pointer, and then copying anything you like to that new block (so long as you remain within the allocated bounds of the memory block allocated).
Look things over and let me know if you have further questions.
1) If I just initialize a char pointer and assign a string to it, where is this information living? In the heap? In the stack? Ex: char *pointer = "Hello world";
The string literal "Hello world" has static storage duration. This means it exists somewhere in memory accessible to your program, for as long as your program is running.
The exact place where it is located is implementation specific.
2) I tried to use malloc to initialize my char pointer and use it later to assign a string to it, but I can't compile it, I get error, what is wrong with this logic? this is what I'm trying to do:
char *pointer = malloc(sizeof(char) * 12);
*pointer = "Hello world";
This doesn't work, since *pointer is the first char in the dynnamically allocated memory (returned by malloc()). The string literal "Hello world" is represented as an array of characters. An array of characters cannot be stored in a single char.
What you actually need to do in this case is copy data from the string literal to the dynamically allocated memory.
char *pointer = malloc(sizeof(char) * 12);
strcpy(pointer, "Hello world"); /* strcpy() is declared in standard header <string.h> *
Note that this doesn't change the data that represents the string literal. It copies the data in that string literal into the memory pointed at by pointer (and allocated dynamically by malloc()).
If you really want pointer to point at the (first character of) the string literal, then do
const char *pointer = "Hello world";
The const represents the fact that modifying a string literal gives undefined behaviour (and means the above prevents using pointer to modify that string literal).
If you want to write really bad code you could also do
char *pointer = "Hello world"; /* Danger Will Robinson !!!! */
or (same net effect)
char *pointer;
pointer = "Hello world"; /* Danger Will Robinson !!!! */
This pointer can now be used to modify contents of the string literal - but that causes undefined behaviour. Most compilers (if appropriately configured) will give warnings about this - which is one of many hints that you should not do this.
Long question but the answer is very easy. Firstly you need to understand what the pointer is.
*pointer = "Hello world";
Here you try to assign a pointer to the char. If you remove the * then you will assign the pointer to the string literal to the pointer.
Unless you have overloaded the assign operator it will not copy it to the allocated memory. Your malloc is pointless as you assign new value to the pointer and the memory allocated by the malloc is lost
You need to strcpy it instead
where is this information living?
It is implementation dependant where the string literals are stored. It can be anywhere. Remember that you can't modify the string literals. Attempt to do so is an Undefined Behaviour
I know that the name of a declared array is just like a pointer to the first element of the array,…
This is not correct. An array behaves similarly to a pointer in many expressions (because it is automatically converted), but it is not just like a pointer to the first element. When used as the operand of sizeof or unary &, an array will be an array; it will not be converted to a pointer. Additionally, an array cannot be assigned just like a pointer can; you cannot assign a value to an array.
… but that array will live in the stack of the memory.
The storage of an array depends on its definition. If an object is defined outside of any function, it has static storage duration, meaning it exists for the entire execution of the program. If it is defined inside a function without _Thread_local or static has automatic storage duration, meaning it exists until execution of its associated block of code ends. C implementations overwhelmingly use the stack for objects of automatic storage duration (neglecting the fact that optimization can often make use of the stack unnecessary), but alternatives are possible.
On the other hand, we use malloc when we want to use the heap of the memory, but I found that you can just initialize a char pointer and assign a string to it on the very same declaration line, so I have some questions regarding this matter:
1) If I just initialize a char pointer and assign a string to it, where is this information living? In the heap? In the stack? Ex: char *pointer = "Hello world";
For the string literal "Hello world", the C implementation creates an array of characters with static storage duration, the same as if you had written char MyString[12]; or int x; at file scope. Assuming this array is not eliminated or otherwise altered by optimization, it is in some general area of memory that the C implementation uses for data built into the program (possibly a “.rodata” or similar read-only section).
Then, for char *pointer, the C implementation creates a pointer. If this definition appears outside a function, it has static storage duration, and the C implementation uses some general area of memory for that. If it appears inside a function, it has automatic storage duration, and the C implementation likely uses stack space for it.
Then, for the = "Hello world", the C implementation uses the array to initialize pointer. To do this, it converts the array to a pointer to its first element, and it uses that pointer as the initial value of pointer.
2) I tried to use malloc to initialize my char pointer and use it later to assign a string to it, but I can't compile it, I get error, what is wrong with this logic? this is what I'm trying to do:
char *pointer = malloc(sizeof(char) * 12);
*pointer = "Hello world";
The second line is wrong because *pointer has a different role in a declaration than it does in an expression statement.
In char *pointer = …;, *pointer presents a “picture” of what should be a char. This is how declarations work in C. It says *pointer is a char, and therefore pointer is a pointer to a char. However, the thing being defined and initialized is not *pointer but is pointer.
In contrast, in *pointer = "Hello world";, *pointer is an expression. It takes the pointer pointer and applies the * operator to it. Since pointer is a pointer to char, *pointer is a char. Then *pointer = "Hello world"; attempts to assign "Hello world" to a char. This is an error because "Hello world" is not a char.
What you are attempting to do is to assign a pointer to "Hello world" to pointer. (More properly, a pointer to the first character of "Hello world".) To do this, use:
pointer = "Hello world";

C uninitialized local variable used when variable is in scope [duplicate]

This question is meant to be used as reference for all frequently asked questions of the nature:
Why do I get a mysterious crash or "segmentation fault" when I copy/scan data to the address where an uninitialised pointer points to?
For example:
char* ptr;
strcpy(ptr, "hello world"); // crash here!
or
char* ptr;
scanf("%s", ptr); // crash here!
A pointer is a special type of variable, which can only contain an address of another variable. It cannot contain any data. You cannot "copy/store data into a pointer" - that doesn't make any sense. You can only set a pointer to point at data allocated elsewhere.
This means that in order for a pointer to be meaningful, it must always point at a valid memory location. For example it could point at memory allocated on the stack:
{
int data = 0;
int* ptr = &data;
...
}
Or memory allocated dynamically on the heap:
int* ptr = malloc(sizeof(int));
It is always a bug to use a pointer before it has been initialized. It does not yet point at valid memory.
These examples could all lead to program crashes or other kinds of unexpected behavior, such as "segmentation faults":
/*** examples of incorrect use of pointers ***/
// 1.
int* bad;
*bad = 42;
// 2.
char* bad;
strcpy(bad, "hello");
Instead, you must ensure that the pointer points at (enough) allocated memory:
/*** examples of correct use of pointers ***/
// 1.
int var;
int* good = &var;
*good = 42;
// 2.
char* good = malloc(5 + 1); // allocates memory for 5 characters *and* the null terminator
strcpy(good, "hello");
Note that you can also set a pointer to point at a well-defined "nowhere", by letting it point to NULL. This makes it a null pointer, which is a pointer that is guaranteed not to point at any valid memory. This is different from leaving the pointer completely uninitialized.
int* p1 = NULL; // pointer to nowhere
int* p2; // uninitialized pointer, pointer to "anywhere", cannot be used yet
Yet, should you attempt to access the memory pointed at by a null pointer, you can get similar problems as when using an uninitialized pointer: crashes or segmentation faults. In the best case, your system notices that you are trying to access the address null and then throws a "null pointer exception".
The solution for null pointer exception bugs is the same: you must set the pointer to point at valid memory before using it.
Further reading:
Pointers pointing at invalid data
How to access a local variable from a different function using pointers?
Can a local variable's memory be accessed outside its scope?
Segmentation fault and causes
What is a segmentation fault?
Why do I get a segmentation fault when writing to a string initialized with "char *s" but not "char s[]"?
What is the difference between char s[] and char *s?
Definitive List of Common Reasons for Segmentation Faults
What is a bus error?
Pointers only point to a memory location. You created a pointer but you did not bind to a memory location yet. strcpy wants you to pass two pointers (first one mustn't be constant) that point to two character arrays like this signature:
char * strcpy ( char * destination, const char * source );
sample usage:
char* ptr = malloc(32);
strcpy(ptr, "hello world");
char str[32];
strcpy(str, "hello world");
You can try the following code snippet to read string until reaching newline character (*you can also add other whitespace characters like "%[^\t\n]s"(tab, newline) or "%[^ \t\n]s" (space, tab, newline)).
char *ptr = malloc(32);
scanf("%31[^\n]", ptr);
(In real life, don't forget to check the return value from scanf()!)
One situation that frequently occurs while learning C is trying to use single quotes to denote a string literal:
char ptr[5];
strcpy(ptr, 'hello'); // crash here!
// ^ ^ because of ' instead of "
In C, 'h' is a single character literal, while "h" is a string literal containing an 'h' and a null terminator \0 (that is, a 2 char array). Also, in C, the type of a character literal is int, that is, sizeof('h') is equivalent to sizeof(int), while sizeof(char) is 1.
char h = 'h';
printf("Size: %zu\n", sizeof(h)); // Size: 1
printf("Size: %zu\n", sizeof('h')); // likely output: Size: 4
This happens because you have not allocated memory for the pointer char* ptr .
In this case you have to dynamically allocate memory for the pointer.
Two functions malloc() and calloc() can be used for dynamic memory allocation.
Try this code :-
char* ptr;
ptr = malloc(50); // allocate space for 50 characters.
strcpy(ptr, "hello world");
When the use of *ptr over don't forget to deallocate memory allocated for *ptr .This can be done using free() function.
free(ptr); // deallocating memory.
Size of dynamically allocated memory can be changed by using realloc().
char *tmp = realloc(ptr, 100); // allocate space for 100 characters.
if (! tmp) {
// reallocation failed, ptr not freed
perror("Resize failed");
exit(1);
}
else {
// reallocation succeeded, old ptr freed
ptr = tmp;
}
In most cases "segmentation fault" happens due to error in memory allocation or array out of bound cases.
For making a modifiable copy of a string, instead of using malloc, strlen and strcpy, the POSIX C library has a handy function called strdup in <string.h> that will return a copy of the passed-in null-terminated string with allocated storage duration. After use the pointer should be released with free:
char* ptr;
ptr = strdup("hello world");
ptr[0] = 'H';
puts(ptr);
free(ptr);

what's difference between struct->char_member = "" and strcat(struct->char_member,"string")?

I have the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct test {
char *str;
};
int main(void)
{
struct test *p = malloc(sizeof(struct test));
p->str = "hello world";
printf("%s\n",p->str);
return 0;
}
It works fine. But when I write like this:
struct test *p = malloc(sizeof(struct test));
p->str="hello";
strcat(p->str," world");
or this:
struct test *p = malloc(sizeof(struct test));
strcat(p->str,"hello world");
I got a segmentation fault.
And I found some relevant explanation here:
You are allocating only memory for the structure itself. This includes the pointer to char, which is only 4 bytes on 32bit system, because it is part of the structure. It does NOT include memory for an unknown length of string, so if you want to have a string, you must manually allocate memory for that as well
Allocate memory for a struct with a character pointer in C
With the explanation, I know the correct code should be like this if I want to use strcat:
struct test *p = malloc(sizeof(struct test));
p->str = malloc(size);
strcat(p->str,"hello world");
So my question is why p->str = "hello world" does not need allocate memory but strcat(p->str,"hello world") needs allocate memory before use?
My compiler is "gcc (Debian 4.9.2-10) 4.9.2". My English is pretty basic, please don't mind :)
"hello, world", "hello", and " world" are all string literals; they are all stored as arrays of char such that they are available as soon as the program starts and are visible over the lifetime of the program.
The statement
p->str = "hello, world";
copies the address of the string literal to p->str. This works fine for the printf statement and anything else that just needs to read the string. However, in the statements
p->str = "hello";
strcat( p->str, " world" );
you are trying to modify the string literal "hello" by appending the string " world" to it. String literals are not modifiable, and attempting to do so leads to undefined behavior, which in your case is a segfault - on many popular desktop platforms, string literals are saved in a read-only section of memory.
Therefore, you need to set aside a region of memory that you can write to. You can either do it dynamically with
p->str = malloc( SOME_SIZE); // enough space to store your final string
strcpy( p->str, "hello" ); // copy the contents of "hello" to the memory str points to
strcat( p->str, " world" ); // append the contents of " world" to the memory str points to
or you can set p->str to point to an array you've declared elsewhere
char buffer[SOME_SIZE];
p->str = buffer; // assigns the *address* of buffer to p->str
or you can declare str as an array of char in the struct definition:
struct test
{
char str[SOME_SIZE];
};
where SOME_SIZE is big enough to hold whatever string you want to store. Note that in this case, p->str = "hello" won't work; you can't use the = operator to assign the contents of arrays to each other; you must use strcpy in that case.
Obviously, dynamic allocation with malloc or calloc is more flexible; you can allocate exactly as much memory as you need, and you can grow or shrink the dynamic buffer as necessary using realloc You just need to remember to free p->str when you're done.
You can still assign the address of a string literal to p->str, just be aware that you cannot pass that address to functions like strcpy or strcat or strtok or any other functions that attempt to modify the contents of the input string.
To be clear, assigning to p->str is not what requires an allocation. p->str is just a memory address, and you can put in any memory address, valid or not. You need an allocation when you want to manipulate the content of the memory address.
In the case of p->str = "hello world", the compiler reserves ahead of time a region of memory and puts the "hello world" string in it, and uses that address.
Notice how the second argument to strcat is a string literal too, and it didn't need to be allocated.
In the first example, you are assigning an immutable string to p->str (this is stored in read-only memory). Thus trying to change the memory results in a seg-fault.
In the second example, you are failing to allocate space for p->str using malloc. Since p is uninitialized, you are reading from some random place in memory you don't own.
Try:
struct test *p = malloc(sizeof(struct test));
p->str=(char *)malloc(12 * sizeof(char));
strcpy(p->str, "hello");
strcat(p->str," world");
Here we have malloc'd just enough space for "hello world" (plus the '\0' character). strcpy copies the string "hello" to the place in memory you have allocated. Now strcat succeeds because you "own" the memory that p->str points to.
Also don't forget to free() memory that you have malloc'd!
EDIT: As a side note, I think you may be getting confused about allocating memory for the struct. In this case allocating memory for the struct only gives you enough memory for a char *; however you have not allocated the memory for the actual pointer to point to.
It is actually unnecessary to allocate memory for struct test, and you could get away with only allocating memory for the char *. Better would be:
struct test p;
p.str=(char *)malloc(12 * sizeof(char));
strcpy(p.str, "hello");
strcat(p.str," world");
You're right. But you should use strcpy instead of strcat here, because strcat will append a string to p->str, which is uninitialized.
In fact p->str = "hello world"; will make p->str point to an (anonymous) string litteral. The memory for it is typically allocated automatically at the beginning of the execution of the program.

What is the difference between assigning a string pointer first to allocated memory and directly to a string literal?

So my understanding is that these two block of codes are valid and do the same thing.
1.)
char *ptr = malloc(5);
ptr = "hi";
2.)
char *ptr = "hi";
I would want to know the difference between the two like if there any advantages of one over the other.
The former is a bug, and that code should never have been written.
It overwrites the pointer returned by malloc() with the address of a string literal, dropping the original pointer and leaking memory.
You must use strcpy() or some other memory-copying method to initialize newly allocated heap memory with a string.
The second just assigns the (run-time constant) address of the string literal to the pointer ptr, no characters are copied anywhere.
The first bit is a possible memory leak, the second relies on the implicit const storage class being used, and assigns the memory address of an immutable string to a pointer.
Basically:
char *ptr = malloc(5);//allocates 5 * sizeof *ptr
//then assigns the address where this block starts to ptr
//this:
ptr = "hi";//assigns position of 'h','i', '\0' in read-only mem to ptr
Now, the address you've allocated, that ptr pointed to, still is allocated. The difference is that you have no "handle" on it anymore, because ptr's value changed. There's no pointer pointing to the dynamic memory you allocated using malloc, so it's getting rather tricky to manage the memory... You probably won't be able to free it, and calling free on ptr now will result in undefined behaviour.
If you write:
char *ptr = "hi";
Then you're actually writing:
const char *ptr = "hi";
Which means you can't change the string to which ptr points:
ptr[0] = 'H';//IMBOSSIBRU
Alternatives are:
char string[] = "Hi";//copies Hi\0 to string
//or
char *ptr = malloc(5);
strcpy(ptr, "hi");//requires string.h
The difference between the two snippets above is that the first creates a stack array, the second allocates a block of memory on the heap. Stack memory is easier to manage, faster and just better in almost every way, apart from it being less abundant, and not really usable as a return value...
There is a pool of string literals for every process. Whenever you create a string literal inside your code, the literal is saved in the pool and the string's address (i.e. an address pointing somewhere to the pool) is returned. Therefore, you are creating a memory leak in your first option, because you are overwriting the address you received with malloc.
In the first case
char *ptr = malloc(5);
ptr = "hi";
There is a memory leak and later you are pointing ptr to a string literal "hi" which does require any memory from the heap (that's why there is memory leak).
But if you are allocating the memory and if you are using
strcpy (ptr, "hi");
then if you wish you can modify it
strcpy (ptr, "hello")
with one condition that you allocate sufficient memory before.
But in your case you are assigning a pointer ptr with a string literal, here you will not be able to modify it
ptr = "hello" // not valid. This will give a segmentation fault error
In your second case there is no memory leak and you are making a pointer to point to a string literal and thus it's value cannot be modified as it will be stored in read only data segment.

C: realloc() not functioning as expected

If I have a variable, str that I would like to allocate memory to on the heap, I would use malloc() like:
char* str = (char*)malloc(sizeof("Hello"));
malloc() is returning a void* pointer, which is the memory location where my memory is.
So now, I can give it some data
str = "Hello";
So, the memory location is now full, with 6 bytes. Now, I want to increase its size, to contain the string "Hello World". So, I use realloc(). According to man, void* realloc(void *ptr, size_t size) will:
The realloc() function changes the size of the memory block pointed to by ptr to size bytes.
The contents will be unchanged in the range from the start of the region up to the minimum of
the old and new sizes. If the newsize is larger than the old size, the added memory will not
be initialized.
So I assumed that it will return a void* to the new, now bigger memory location, which I can now fill with my new string, so going on the same logic to malloc():
str = (char*)realloc(str, sizeof("Hello World"));
But, this is where the problem is. This will cause:
*** Error in `./a.out': realloc(): invalid pointer: 0x0000000000400664 ***
And in valgrind
Invalid free() / delete / delete[] / realloc()
This suggests that there is something wrong with the pointer, str. So I decided to remove:
str = "Hello";
And it compiles fine, with the following code:
char* str = (char*)malloc(sizeof("Hello"));
str = (char*)realloc(str, sizeof("Hello World"));
I am aware of the fact that pointer to realloc() must come from malloc(), but simply assigning data to it shouldn't cause realloc() to fail, which suggects that I am doing something completly wrong.
So, what am I doing wrong?
And here is the code that fails:
char* str = (char*)malloc(sizeof("Hello"));
str = "Hello";
str = (char*)realloc(str, sizeof("Hello World"));
// str = "Hello World"; - this is what I would to be able to do.
Note: This code is something I have stripped down from a much larger program, just
to demonstrate the problem I am having, so I have removed checks etc.
Also, I am very new to C, so hence the really simple problem (sorry?), but after hours of work and research, I still can't figure out what I am doing wrong - It seems to work fine for everyone else!.
In C you cannot copy around blocks of memory as you tried to do:
str = "Hello";
That is not a valid string copy; instead, it leaves your malloc'd memory unaccounted for ("leaked"), and changes the pointer 'str' to point to a hard-coded string.
Further, because str is now a pointer to a hard-coded, static string, you cannot realloc it. It was never malloc'd to begin with!
To fix this, you want to change: str = "Hello"; to this:
strcpy(str, "Hello");
str = "Hello";
is the problem. You allocated a buffer and made str point to it. You then need to copy into that buffer. Like this:
strcpy(str, "Hello");
But instead you changed the value of the pointer.
When you call realloc, you must pass to realloc, a pointer that was created by an earlier call to malloc, realloc or similar. But you did not do that. Because you modified str.
malloc() is returning a void* pointer, which is the memory location where my memory is.
So far so good
So now, I can give it some data
str = "Hello";
You are right on being able to give that memory some data, but you are wrong on a way of doing it: you cannot reassign the pointer to a string literal - this would create a memory leak. Instead, you should copy the data into the memory block, like this:
strcpy(str, "Hello");
If you do an assignment instead of a copy, the pointer no longer points to something returned by malloc, making it illegal to pass that pointer to realloc.
This instruction:
str = "Hello";
doesn't allocate any memory in the heap.
char* str = (char*)malloc(sizeof("Hello"));
You are allocating memory dynamically to the str. Good. You are cast-ing the return value of malloc(), Not good.
str = "Hello";
You are trying to put the address of the static string "Hello" in str. Why? This is actually overwriting the memory address allocated by malloc(). What str contains is not a dynamically allocated pointer right now. It's a static address, which is not eligible for realloc()/ free() . Also, you are taking yourself into a zone of memory leak. What I think is you need strcpy() instead.
if you want to avoid the reallocation of memory issue use the function strdup :
char *str = strdup("hello");
str = strdup("hello word");
strdup returns a pointer to the storage space containing the copied string. If it cannot reserve storage strdup returns NULL.

Resources