#include <stdio.h>
#include <stdlib.h>
int main()
{
char *ptr = malloc(sizeof(char) * 1);
ptr = "Hello World";
puts(ptr);
getchar();
}
im not a malloc() expert but isn't that code supposed to give an error since i allocated only one byte but assigned a value that contains 11 bytes to *ptr pointer ?
or does the H get stored in the place i assigned and then the rest of the string just goes in the places after it ?
You are reassigning the pointer 'ptr' to another block of memory, so you won't see any error. However, the block of memory (size 1) that you allocated is "lost" and leads to a memory leak.
When using malloc you're requesting some memory and malloc returns the first address of that memory (if it can be given). When you re-assign the pointer you're not doing anything with the memory it points to. You just change what the pointer points to.
What you're doing here is technically valid C but you're creating a memory leak because you lose the address of the malloced memory, which you must free when you're done with it.
Related
#include <stdlib.h>
#include <stdio.h>
char* get_string(){
// char* pointer = malloc(sizeof(char)*10);
char* pointer = "string";
printf("%s\n",pointer);
return pointer;
}
int main(){
// char* got = malloc(sizeof(char)*10);
char* got = get_string();
printf("%s\n",got);
// free(got);
}
This block of code gives no warning in testing.
But my question is :
For the following lines of code,
char* got = malloc(sizeof(char)*10);
got = get_string();
Why the malloc here is not needed?
Why there's no need to allocate memory to store the pointer returned from the function?
I am a bit confused now.
Thank you.
Take an example:
int a = 5;
a =6;
now, the value 5 is lost.
Same with your case, too. The pointer returned by malloc(), and stored into got, will be overwritten by the pointer returned by the function call get_string(). So there will be memory leak.
Remember, you're assigning a value to a variable (of pointer type), and for that variable, got, memory is already allocated. You need to make sure that the value of got, i.e., the address held by got points to a valid memory location before you can read/write to/into that location.
In C
const char* my_str = "my str";
creates creates a string "my str" in global static memory and the creates a pointer on the stack that points to that memory. Since "my str" exists for the life of the process, it is safe to return a pointer to it. However if you did:
const char my_str[] = "my str";
return my_str;
You will hit undefined (bad) behaviour. This is because the latter case allocates "my str" on the stack in the function and once the function returns "my str" is popped off the stack. Any pointer returned will be pointing to garbage.
In C++ you can only assign string literal to a const char*. C allows you to assign a string literal to a char* but I don't believe writing to the dereferenced pointer is a good idea.
Think of a pointer as a variable that stores values of type address.
malloc is a function that returns the address of a place in memory that can store the desired size passed as parameter.
Once the variables get out of scope (when you reach '}' that closes the first '{' that came before that variable declaration) you lose access to them, their location in memory will become invalid.
What malloc does is keep that place in memory valid until you release it with free.
So if you already called malloc and want to update a pointer, all you have to do is assign that value (address) to the pointer.
I am trying to get my head around dynamic memory allocation and was hoping someone could explain why the following code executes as it does.
#include <stdlib.h>
#include <string.h>
char* create_string(void);
int main(){
char* str1 = NULL;
char* str2 = NULL;
str1 = create_string();
str2 = (char*)malloc(11);
str2 = create_string();
printf("String 1 is: %s", str1);
printf("String 2 is: %s", str2);
free(str1);
}
char* create_string()
{
char* stack_str = "TestString";
char* heap_str = (char*)malloc(strlen(stack_str) + 1);
strcpy(heap_str, stack_str);
if(heap_str == NULL)
{
printf("Oh no");
return NULL;
}
return heap_str;
}
As far as I thought, to allocate memory on the heap, you have to use malloc with a size which allocates a block of memory and then use a function such as strcpy() or memcpy(), as I have done with str2 above (malloc 11 for the size of "TestString" plus one for the null terminator.)
I am just confused why assigning the result of create_string to str1 which is a null pointer which has not been allocated a block of memory produces the same output as str2.
Many thanks in advance!
"As far as I thought, to allocate memory on the heap, you have to use malloc with a size which..."
size in malloc() is number of bytes which is unsigned integer. Therefore syntactically str2 = (char*)malloc(11); is correct.
Both str1 and str2 are pointing to different memory locations from the heap containing "TestString". This is according to what you have programmed. However
str2 = (char*)malloc(11); returns 11 bytes of memory that can store character data type and returns a pointer to this location in heap. There is no issue in this.
However, in your code you have leaked this allocation when you assign create_string() pointer to it.
It is not wroking exactly as you think.
Firstly, C has constant strings, which will be initialized by double quotes. Those objects when used, actually return a pointer that points to the location of the initialized constant string array.
char * ptr="something" //"something" return a pointer to the location of the string array
// and is assigned to the ptr.
You don't need to allocate memory for constant string as they are managed by compilers. What's happening in the code is stack_str locates to this constant string array which is managed by the compiler. So it is always present. You create a memory block and stores the address in heap_str, and copies the stack_str contents to the dynamically allocated memory, and returns the pointer.
In effect,
str2 = (char*)malloc(11);
is not used for anything and is wasted. Hope you understands.
Edit: In your create_str(), you check heap_str isn't NULL AFTER strcpy(). If the malloc() failed for some reason, the program will still crash even if you check for NULL.
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.
I have simple code,
#include "stdafx.h"
#include <malloc.h>
int main()
{
char *p = (char*) malloc(10);
p = "Hello";
free(p);
return 0;
}
This code is giving run time exception while terminating. Below is error snippiest,
Microsoft Visual C++ Debug Library
Debug Assertion Failed!
Program: ...\my documents\visual studio 2010\Projects\samC\Debug\samC.exe
File: f:\dd\vctools\crt_bld\self_x86\crt\src\dbgheap.c
Line: 1322
Expression: _CrtIsValidHeapPointer(pUserData)
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
(Press Retry to debug the application)
Abort Retry Ignore
p = "Hello"; makes p point to a string literal and discards the previously assigned value. You can't free a string literal. You can't modify it.
If you want p to hold that string, just use
char* p = "Hello";
or
char p[] = "Hello";
if you plan on modifying it.
Neither requires free.
This is how you write a string in the memory allocated by malloc to a char pointer.
strcpy(p, "Hello");
Replace the line
p = "Hello";
with the strcpy one & your program will work fine.
You also need to
#include <string.h>
malloc returns a pointer to allocated memory. Say the address is 95000 (just a random number I pulled out).
So after the malloc - p will hold the address 95000
The p containing 95000 is the memory address which needs to be passed to free when you are done with the memory.
However, the next line p = "Hello"; puts the address of the string literal "Hello" (which say exists at address 25000) into p.
So when you execute free(p) you are trying to free 25000 which wasn't not allocated by malloc.
OTOH, when you strcpy, you copy the string "Hello" into the address starting at p (i.e. 95000). p remains 95000 after the strcpy.
And free(p) frees the right memory.
You can also avoid the malloc and use
char *p = "Hello";
However, in this method, you cannot modify the string.
i.e. if after this you do *p = 'B' to change the string to Bello, it becomes an undefined operation. This is not the case in the malloc way.
If instead, you use
char p[] = "Hello";
or
char p[10] = "Hello";
you get a modifiable string which need not be freed.
p = "Hello";
free(p);
Since Hello is statically allocated, you cannot free it. I'm not sure why you allocate some memory just to throw the pointer away by changing it to another pointer, but that has no effect. If you do this:
int i = 1;
i = 2;
i has no memory that it once held a 1, it holds a 2 now. Similarly, p has no memory that it once held a pointer to some memory you allocated. It holds a pointer to an immutable constant now.
this is a nice one.
the char sequence "hello" is constant and therefore placed niether on the heap nor the stack, but in the .bss/.data segment. when you do p="hello" you make p point to the address of the string hello in that segment instead of the memory you alocated on the heap using malloc. when you go to free p it tries to free the memory in the .bss/.data segment, and naturally fails.
what you probably want is something like strcpy(p,"hello"); which goes over every char in "hello" and places it in the memory pointed to by p. essentially creating a copy of the string "hello" at memory address p.
If you want to copy the contents of the string "Hello" to the memory you allocated, you need to use strcpy:
strcpy(p, "Hello");
The line
p = "Hello";
assigns the address of the string literal "Hello" to the pointer p, overwriting the pointer value that was returned from malloc, hence the crash when you call free.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C Array Instantiation - Stack or Heap Allocation?
When dynamically allocating a struct containing a char pointer, what happens with the actual char pointer? Where is it stored?
And once the struct is freed, is the char pointer freed along with it?
For example consider the following struct:
struct mix
{
int a;
float b;
char *s;
};
typedef struct mix mix;
And then the following code that allocates memory for it:
int main()
{
mix *ptr = (mix*)malloc(sizeof(mix));
ptr->a = 3;
ptr->b = 4.5f;
ptr->s = "Hi, there, I'm just a really long string.";
free(ptr);
return 0;
}
Is *s allocated on the stack and then freed along with *ptr? I can imagine it is indeed allocated on the stack as it's not in any way dynamically allocated (unless malloc has some functionality I'm not aware of). And I guess 'going out of scope' for *s would be at the point of freeing *ptr. Or have I got it completely wrong? :)
Thanks very much!
The space for the char* member named s is allocated on the heap, along with the rest of the members of mix after the call to malloc() (whose return value you do not need to cast). The string literal to which s is assigned is not allocated on the heap or the stack, but is part of the actual binary and has static storage duration. So this:
ptr->s = "Hi, there, I'm just a really long string.";
assigns the address of the string literal to ptr->s. If you want ptr->s to point to something other than a string literal then you need to malloc() memory for it. And for every malloc() there must be a free() so ptr->s would need to be free()d before ptr is (if ptr->s is pointing to dynamically allocate memory only).
After the call to free(), dereferencing ptr is undefined behaviour.
When you dynamically allocate mix with malloc(), you are actually allocating a block of memory to store mix structure data members, i.e.
an int (a)
a float (b)
a pointer to a char (s)
And when you call free(), you just release that block.
So, you don't allocate the string, you just allocate the string pointer.
If you want to dynamically allocate the string, you must do it explicitly (with another call to malloc()), and to avoid memory leaks you should also free the string explicitly, using free().
When you malloc for ptr, memory is allocated for all members of the struct including the pointer s which is no different to memory allocated for any other member of the struct.
You are assigning a string literal to s, so it's fine which is usually stored in the read-only section. Otherwise, you'll need to malloc for the ptr->s as well and free. Since, it's a string literal, there's no need to free s here (doing so is UB).
mix* ptr is allocated on the stack. The contents that ptr point at, a variable of type mix, is allocated dynamically on the heap, including the pointer s.
Please note that s doesn't point at anything, the pointer doesn't do anything useful. You have to set it to point at something, which could be allocated anywhere. Whatever it points to is not freed when your struct is freed. In this case you set it to point at a constant string literal allocated in ROM, so you won't need to worry about that.
Is *s allocated on the stack
*s (that is, the result of dereferencing the pointer s) isn't allocated at all. Following the malloc, ptr->s is an uninitialized pointer. It doesn't point to anything, and the expression *(ptr->s) has undefined behavior until you do ptr->s = "Hi, etc".
Once you've initialized ptr->s to point to the string literal, *(ptr->s) is the first character of the string literal, so it probably exists in some data section of the executable. Nothing is dynamically allocated other than the sizeof(mix) bytes for the struct (probably 12 bytes on a 32bit implementation).
what happens with the actual char pointer? Where is it stored?
char* is also like other members, take some bytes(take 8 byte in 64 bit machine, similar to other pointer). In your case, you are allocating memory for that structure instance in heap. so the memory for this pointer also will be allocated in same heap block which is allocated for that structure instance.
Consider this code. This gives where the char* will be:
#include <stdio.h>
typedef struct
{
int a;
float b;
char *s;
}mix;
int main()
{
printf("\n%d ,float:%d, int:%d, char*:%d", sizeof(mix), sizeof(float), sizeof(int), sizeof(char*));
return 0;
}
so size of this structure is 16 bytes. consist of 4 byte integer, 4 byte float and 8 byte char*. (In 64 bit OS, char* will be 4 bytes if OS is 32 bit.)
And once the struct is freed, is the char pointer freed along with it?
Usually the block which is pointed by char* will not be freed(If it points to a block allocated by malloc()). only the structure block will be freed. we know free() needs valid address which is returned during allocation for peaceful de-allocation. If you free without freeing that char*, it will leads to memory leak.
But your case "Hi, there, I'm just a really long string.";
the above given string is string literal which is allocated in read-only section of your program.
use gcc -S Yourprogram.c
This will generate .s file. You can look at .read_only section for this string. so even you delete your structure instance, there will be no memory leak. Because you are just pointing a address which is read-only. You are not at-all allocating memory for this string.