Is malloc needed for this int pointer example? - c

The following application works with both the commented out malloced int and when just using an int pointer to point to the local int 'a.' My question is if this is safe to do without malloc because I would think that int 'a' goes out of scope when function 'doit' returns, leaving int *p pointing at nothing. Is the program not seg faulting due to its simplicity or is this perfectly ok?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct ht {
void *data;
} ht_t;
ht_t * the_t;
void doit(int v)
{
int a = v;
//int *p = (int *) malloc (sizeof(int));
//*p = a;
int *p = &a;
the_t->data = (void *)p;
}
int main (int argc, char *argv[])
{
the_t = (ht_t *) malloc (sizeof(ht_t));
doit(8);
printf("%d\n", *(int*)the_t->data);
doit(4);
printf("%d\n", *(int*)the_t->data);
}

Yes, dereferencing a pointer to a local stack variable after the function is no longer in scope is undefined behavior. You just happen to be unlucky enough that the memory hasn't been overwritten, released back to the OS or turned into a function pointer to a demons-in-nose factory before you try to access it again.

Not every UB (undefined behaviour) results in a segfault.
Normally, the stack's memory won't be released back to the OS (but it might!) so that accessing that memory works. But at the next (bigger) function call, the memory where the pointer points to might be overwritten, so your data you felt like bing safe there is lost.

malloc() inside a function call will work because it stores on heap.
The pointer remains until you free the memory.
And yes, not every undefined behaviour will result in segmentation fault.

It does not matter that p does not point at anything on return from doit.
Because, you know, p isn't there any more either.
It does matter that you are reading the pointer to a no-longer-existing object in main though. That's UB, but harmless on most modern platforms.
Even worse though, you are reading the non-existent object it once pointed to, which is straight Undefined Behavior.
Still, nobody is obliged to catch you:
Can a local variable's memory be accessed outside its scope?
As an aside, Don't cast the result of malloc (and friends).
Also, be aware that not free-ing memory is not harmless on all platforms: Can I avoid releasing allocated memory in C with modern OSes?

Yes, the malloc is needed, otherwise the pointer would point on the 4-byte space of the stack, which would be used by other data, if you called other functions or created now local variables.
You can see that if you call that function afterwards with a value of 10:
void use_memory(int i)
{
int f[128]={};
if(i>0)
{
use_memory(i-1);
}
}

Related

Freeing a pointer inside a function, and using it in main

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
char* test() {
char* s = "Hello World";
size_t len = strlen(s);
char* t = malloc(sizeof(char)*(len+1));
strcpy(t, s);
free(t);
return t;
};
int main(void) {
printf("%s\n", test());
return 0;
};
I would like to allocate and de-allocate memory inside the function. I tested this code and works, but I am wondering:
Why does this work?
Is it good practice to use the value of a freed pointer in main ?
Once you call free on a pointer, the memory it pointed to is no longer valid. Attempting to use a pointer to freed memory triggers undefined behavior. In this particular case it happened to work, but there's no guarantee of that.
If the function returns allocated memory, it is the responsibility of the caller to free it:
char* test() {
char* s = "Hello World";
size_t len = strlen(s);
char* t = malloc(sizeof(char)*(len+1));
strcpy(t, s);
return t;
};
int main(void) {
char *t = test();
printf("%s\n", t);
free(t);
return 0;
};
malloc reserves memory for use.
free releases that reservation. In general, it does not make the memory go away, it does not change the contents of that memory, and it does not alter the value of the pointer that held the address.
After free(t), the bytes of t still contain the same bit settings they did before the free. Then return t; returns those bits to the caller.
When main passes those bits to printf, printf uses them as the address to get the characters for %s. Since nothing has changed them, they are printed.
That is why you got the behavior you did with this program. However, none of it is guaranteed. Once free was called with t, the memory reservation was gone. Something else in your program could have used that memory. For example, printf might have allocated a buffer for its own internal use, and that could have used the same memory.
For the most part, malloc and free are just methods of coordinating use of memory, so that different parts of your program do not try to use the same memory at the same time for different purposes. When you only have one part of your program using allocated memory, there are no other parts of your program to interfere with that. So the lack of coordination did not cause your program to fail. If you had multiple routines in your program using allocated memory, then attempting to use memory after it has been released is more likely to encounter problems.
Additionally, once the memory has been freed, the compiler may treat a pointer to it as if it has no fixed value. The return t; statement is not required to return any particular value.
It doesn't matter where do you free() a pointer. Once it is free()d, the pointer is not deferrenciable anymore (neither inside nor ouside the function where it was free()d)
The purpose of free() is to return the memory allocated with malloc() so the semantics are that, once you have freed a chunk of memory, it is not anymore usable.
In C, all parameters are passed by value, so free() cannot change the value expression you passed to it, and this is the reason the pointer is not changed into an invalid pointer value (like NULL) but you are advised that no more uses of the pointer can be done without incurring in Undefined Behaviour.
There could be a solution in the design of free() and it is to pass the pointer variable that holds the pointer by address, and so free() would be able to turn the pointer into a NULL. But this not only takes more work to do, but free() doesn't know how many copies you have made of the value malloc() gave to you... so it is impossible to know how many references you have over there to be nullified. That approach makes it impossible to give free() the responsibility of nullifying the reference to the returned memory.
So, if you think that free doesn't turn the pointer into NULL and for some strange reason you can still use the memory returned, don't do it anymore, because you'll be making mistakes.
You are adviced! :)

When writing a function that returns pointer, why should I allocate memory to the pointer I'm going to return?

I'm a bit weak when it comes to memory allocation and pointers.
So, I want to understand why do I have to allocate memory to pointers in functions as follow:
char *cstring(char c, int n)
{
int i = 0;
char * res;
res = malloc ((n+1)*sizeof(char));
while (i<n)
{
res[i]=c;
i++;
}
res[i] ='\0';
return res;
}
and why is the following not valid?
char *cstring(char c, int n)
{
int i = 0;
char * res;
while (i<n)
{
res[i]=c;
i++;
}
res[i] ='\0';
return res;
}
I understand that I should allocate memory (generally) to pointers so that they have defined memory.
However, I want to mainly understand how is it related to the concept of stack and heap memories!
Thanks in advance!
Pointers need to point to a valid memory location before they can be dereferenced.
In your first example, res is made to point at a block of allocated memory which can subsequently be written to and read from.
In your second example, res remains uninitialized when you attempt to dereference it. This causes undefined behavior. The most likely outcome in this case is that whatever garbage value it happens to contain will not be a valid memory address, so when you attempt to dereference that invalid address your program will crash.
If you declare a variable like that,
int A = 5;
then that means the variable will be on the stack. When functions are called, their local variables are pushed to the stack. The main function is also an example of that. So you don't have to allocate memory manually, your compiler will do this for you in the background before it calls your main function. And that also means if you examine the stack during the execution of the function you can see the value 5.
With this,
int A = 5;
int *PtrToA = &A;
The pointer will be on the stack again. But this time, the value on the stack just shows the memory address of the actual integer value we want. It points to the address of the memory block that holds the value 5. Since A is held in the stack here, pointer will show a memory address on the stack.
Like the case in your question you can allocate memory dynamically. But you have to initialize it before you read it. Because when you request to allocate the memory, your operating system searches for a valid memory field in your programs heap and reserves that for you. Than it gives you back its adddress and gives you the read write permissions so you can use it. But the values in it won't contain what you want. When compiler allocates on stack, the initial values will be unset again. If you do this,
char *res;
res[1] = 3;
variable res will be on the stack and it will contain some random value. So accessing it is just like that,
(rand())[1] = 3;
You can get an access violation error because you may not have permission to write to that memory location.
An important note; after your function call returns, values of local variables on the stack are no more valid. So be careful with that. Do not dereference them after the function call ends.
In conclusion; if you want to use a pointer, be sure it points to a valid memory location. You can allocate it yourself or make it point another memory address.
The second version of your code declares a pointer, but does not initialize it to point to a valid memory address.
Then, the code dereferences that pointer -- during the loop. So, your code would access uninitialized memory in this case. Remember, array indexing is just syntactic sugar for dereferencing -- so your code accesses memory its not supposed to.
The first version of your code initializes the pointer to actually point to something, and hence when you dereference it during the loop, it works.
Of course, in either case, you return the pointer from the function -- its just that in the first version it points to something valid, whereas in the second version it points anywhere.
The moral here is to always initialize your variables. Not doing so could result in undefined behavior in your code (even if it appears to work sometimes). The general advice here is to always compile your code using at least some compilation flags. For example in gcc/clang, consider -Wall -Werror -Wextra. Such options often pick up on simple cases of not initializing variables.
Also, valgrind is a brilliant tool for memory profiling. It can easily detect uses of uninitialized memory at runtime, and also memory leaks.
Simple: because you do not have any allocated memory for the data you wite. In your example you define pointer, you do not initialize it so it will reference random (or rather not possible to predict) place in the memory, then you try to write to this random memory location.
You have 2 Undefined Behaviours here in 5 lines example. Your pointer is not initialized, and you did not allocate any valid memory this pointer to reference.
EDIT:
VALID
char *cstring(char c, int n)
{
char * res;
res = malloc ((n+1)*sizeof(char));
char *cstring(char c, int n)
{
char * res;
static char buff[somesize];
res = buff;
char buff[somesize];
char *cstring(char c, int n)
{
char * res;
res = buff;
INVALID
char *cstring(char c, int n)
{
char * res;
char buff[somesize];
res = buff;

Do we get a dangling pointer by copying a dangling pointer?

On one hand, if I write the following code :
int* fortytwo_pointer () {
int v = 42;
return &v;
}
I get a dangling pointer and I can check this by calling
printf ("forty two : %d\n", *(fortytwo_pointer()));
On the other hand
int* copy (int *pointer) {
return pointer;
}
int* fortytwo_pointer () {
int v = 42;
return copy (&v);
}
does not produce the same 'Segmentation fault' error.
I would expect it to also be an instance of a dangling pointer because the value v goes out of scope just the same. Is it true ? If so, how to check that the pointer is indeed dangling ?
Edit :
This question is more focused on dynamically checking that a pointer is valid, for example if we get a pointer from a call of a library function. I'm more interested in checking if the code could produce invalid pointers.
Yes, you do. As pointed out in the comments on your question, you cannot "check it" by using printf. From the moment that the function stack is popped, you're dealing with undefined behavior.
Use valgrind to run your program, and it will point out any read/write errors. Those may not cause your program to fail every time, but should be taken care of nonetheless. I'm sure your dangling pointer will show up in there, and valgrind will be kind enough to show you the full trace of where each error occurs.
I would expect it to also be an instance of a dangling pointer because the value v goes out of scope just the same. Is it true ? If so, how to check that the pointer is indeed dangling ?
Yes, the variable you have declared in int* fortytwo_pointer() is a local variable. This means the variable you have declared stores in a stack frame and at the end of this function, the variable is going to become freed and there's no a good address to dereference and that's why v is a dangling pointer.
My suggestion to resolve this problem is allocating memory from heap by using some functions such as malloc() or calloc(). Functions delete all variables in stack, not heap.
So, you can write your code below :
int* fortytwo_pointer () {
int *v = (int*) malloc (sizeof(int));
if(v == NULL)
{
printf("An error occurred.\n");
getch();
}
*v = 42;
return v;
}
and finally, don't forget to free *v pointer. You can free that by using free().

Allocating and initialising a pointer in C

So, I am new to pointers to in C.
I am facing a confusion.
If I have,
int a;
Here, I dont allocate memory manually for a. It's done automatically by the compiler.
Now, if in a similar fashion, if I do,
char * a;
Do I need to allocate memory for the pointer?
Secondly, I made this code,
#include <stdio.h>
int main (void)
{
int *s=NULL;
*s=100;
printf("%d\n",*s);
return 0;
}
Why do I get a seg fault in this code? Is it because I havent allocated memory for the pointer? But as asked in the above question, I can simply declare it as well without manually allocating the memory.
PS: I am new to pointers and I am facing confusion in this. Spare me if it is a bad question. Thanks.
Edit: I read the post for malloc on SO.
http://stackoverflow.com/questions/1963780/when-should-i-use-malloc-in-c-and-when-dont-i
It doesnt really solve my doubt.
You don't need to allocate memory for the pointer itself. That's automatic, like the int in your first code snippet.
What you do need to allocate is the memory that the pointer should point to, and you need to initialize the pointer to point to that.
Since you're not allocating any space, the *s= assignment is undefined behavior. s itself (the pointer) is allocated, and initialized to NULL. You can't dereference (*s - look at what the pointer points to) a null pointer.
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
int *s = NULL; // s is created as a null pointer, doesn't point to any memory
s = malloc(sizeof(int)); // allocate one int's worth of memory
*s = 100; // store the int value 100 in that allocated memory
printf("%d\n",*s); // read the memory back
free(s); // release the memory
// (you can't dereference s after this without
// making it point to valid memory first)
return 0;
}
You have to allocate memory for the variable s you are declaring. Malloc is a nice way to do that. With int *s=NULL the pointer does not point to any address. And after that you trying to give a value to that address (*s=100;). If you do not want to allocate memory manualy (with malloc) you simply declare an int variable and then make s pointing to that variable.
With malloc:
#include <stdio.h> int main (void)
{
int *s=NULL;
s=(int *)malloc(sizeof(int));
*s=100;
printf("%d\n",*s);
return 0;
}
Without malloc:
#include <stdio.h>
int main (void)
{
int *s=NULL;
int var;
s=&var;
*s=100;
printf("%d\n",*s);//100
printf("%d\n",var);//also 100
return 0;
}
As pointers are also special type of variables which stores the address of other variables,As the address is also some value(number), Hence memory is also needed to store this address,so compiler automatically allocates memory(exactly 4 bytes on 32-bit machine) to a pointer variable,when you are allocating the memory using malloc() or calloc()your are actually allocating the memory to the data which is to be stored,and simply assigning the starting address of this memory to the pointer.
In your example at the line
int *s=NULL; //this line
Compiler actually allocates memory of 4 bytes (if your machine is 32-bit)
see this small snippet
int main(void)
{
int *s=NULL;
printf("%d\n",sizeof(s)); //Will output 4 if you are using is 32-bit OS or else 2 if you are using using 16 bit OS.
return 0;
}
And NULL is simply just another way of assigning Zero to a pointer.So technically your actually using 4 bytes to store zeros in that pointer. And don't be confused, assigning zero or NULL means that the pointer is not pointing to any data(as it doesn't hold a valid address,Zero is not valid address).

C++ Allocate and free memory in function

Consider the following code (building with g++):
#include <stdlib.h>
#include <stdio.h>
typedef struct {
int a;
int b;
char c;
} memstr_t;
memstr_t *ptt_backup;
void mmm(memstr_t*& ptt)
{
ptt = (memstr_t *)calloc(15, sizeof(memstr_t));
ptt[0].a = 1;
ptt[0].b = 2;
ptt[0].c = 'c';
ptt_backup = ptt;
}
void fff()
{
free(ptt_backup);
}
int main(int argc, char *argv[])
{
memstr_t *ptt;
mmm(ptt);
printf("%d %d %c\n", ptt[0].a, ptt[0].b, ptt[0].c);
getchar();
//fff();
free(ptt); // same as fff()?
printf("%d %d %c\n", ptt[0].a, ptt[0].b, ptt[0].c); //why works?
getchar();
return 0;
}
I don't understand:
1) Why I'm not getting segfault on the second print since I free the memory? I'm still getting the values which I assigned in mmm()
2) Are free() and fff() doing the same thing?
1) Dereferencing free'd memory can do anything. It may be there, it may not, it is undefined behaviour and could do anything, including faxing your cat.
2) Yes, free() and fff() are doing the same thing as they both point to the same memory location.
Second print uses pointer that is no longer valid, that makes behavior undefined. Whatever can happen, including what makes you believe it "works", and any other time it could be something completely else. DON'T DO THAT!
2: in this code fragment they have the same effect.
calloc allocates memory and returns a pointer to the allocated memory.
In mmm you assign ptt to ptt_backup. Now both of them point to the same place. (Just because I have a name and a nickname , that doesn't make two copies of me. I am a single person accessible via two different names)
In fff you are freeing ptt_backup (read that as freeing the memory pointed by ptt_backup) which is also the one pointed by ptt.It means the memory is not available for you to use now. It can still retain values but its undefined to rely on it. See this nice answer,
Can a local variable's memory be accessed outside its scope?
printf("%d %d %c\n", ptt[0].a, ptt[0].b, ptt[0].c); may not always work.
Then when you do free(ptt) (read that as freeing the memory pointed by ptt) which is already deleted by fff, it is undefined behaviour as stated,
The free() function shall cause the space pointed to by ptr to be
deallocated; that is, made available for further allocation. If ptr is
a null pointer, no action shall occur. Otherwise, if the argument does
not match a pointer earlier returned by the calloc(), malloc(), [ADV]
posix_memalign(), realloc(), or [XSI] strdup() function, or if
the space has been deallocated by a call to free() or realloc(), the
behavior is undefined.
Using a memory pointer that points to freed memory leads to undefined behavior. This means that a segfault doesn't necessarily happen, but is possible. Therefore, you never should dereference freed memory.
They (fff and free) are the same thing in this context, because they point to the same address.
You never allocate memory for ptt_backup! You're in undefined behaviour land; anything could happen in fff()

Resources