Is this an undefined behaviour? - c

So I just wanted to ask is this an undefined behavior when the commented line is added. Although there is no compilation errors and both of them give the same answers. I would like to know is there any difference. Is the address being overwritten by the address of a. Also If one were to do this (i.e allocate memory for b), would memcpy() be a good solution. This may be a trivial example but I would like to understand the difference.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *a;
int *b;
a=malloc(sizeof(int));
//b=malloc(sizeof(int));
int c=6;
a=&c;
b=a;
printf("%d\n",*b);
return 0;
}

When you uncomment //b=malloc(sizeof(int)); part, you'll end up creating memory leak, as later, you'll be losing the pointer returned by malloc() and will have no way to free() it.
FWIW, you already have the issue with a, as you overwrite malloc()ed memory by the address of c.
It is not UB, though, a bad practice, anyway.
For the above code, you can remove both the malloc()s, safely. You don't need them.
That said, int main() should be int main(void), at least, to conform to the standards.

b=malloc(sizeof(int));
int c=6;
a=&c;
b=a;
Since the value of b is changed before it's used, that you assign the return value of malloc to b makes no difference. However, you don't free it, so you do leak the memory allocated.
No UB.

I don't think this code cause undefined behavior, but this code do cause memory leak.
Don't use malloc() if you don't need additional buffer.

Related

Is malloc needed for this int pointer example?

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);
}
}

Using free() on non-heap objects in C

I couldn't find what the behaviour of this action actually is. It doesn't seem to cause any run-time errors so I guess it just does nothing? I found about this technique only recently while I was writing my coursework. Actually, my professor seems to be an advocate of this but I fail to grasp how it works without breaking. Basically, the idea is to use a variable as a test object or guard for a struct pointer, and then pass this "dummy" variable to a function. I'll try giving an example with code:
#include <stdio.h>
#include <stdlib.h>
struct Struct {
int a;
struct Struct *next;
float c;
};
int
stuff(struct Struct *ptr) {
free(ptr);
return 1; // always assume true for the sake of example
}
int
main(int argc, char *argv[]) {
struct Struct *ptr;
struct Struct test;
int retval;
if ((ptr = malloc(sizeof(struct Struct *))) == NULL) {
fprintf(stderr, "ERROR: could not allocate memory\n");
return -1;
}
// some magic goes here...
test = *ptr;
retval = stuff(&test);
if (retval) {
free(ptr);
}
return 0;
}
In my coursework I had to free a struct's two struct pointer members one after another, and then free the struct's memory. Since either of the struct pointer members could be operating on data, if one could not be freed then the whole main struct should not be freed and changes should be reverted. This approach of a variable on the stack to work out whether memory can be safely freed without compromising running data is what's baffling me. I'm not really sure what I'm even not understanding. Would anyone aware of this methodology enlighten me on the details?
couldn't find what the behaviour of [using free() on non-heap objects in C] action actually is.
It's undefined behavior. That's it, you can't make any assumptions about what will occur. test is a copy of the memory at *ptr. Calling free on a pointer which was not returned by malloc (and friends) results in undefined behavior.
Either you misunderstood your professor, or your professor doesn't know what s/he is talking about. All you need do is to read the documentation:
The behavior is undefined if ptr does not match a pointer returned earlier by malloc(), calloc() or realloc(). Also, the behavior is undefined if the memory area referred to by ptr has already been deallocated, that is, free() or realloc() has already been called with ptr as the argument and no calls to malloc(), calloc() or realloc() resulted in a pointer equal to ptr afterwards.
It doesn't seem to cause any run-time errors so I guess it just does nothing?
Welcome to C :). You're used to languages which smack your hand right away when you do something terribly wrong. C doesn't really care what you do. C gives you freedom, but that freedom works both ways (i.e., you're free to shoot your foot off as well).
I ran this test and got a core dump. Ubuntu Linux with gcc 4.6.3. I tried several other variations on the theme and core dumped all of them.
Here is the description of free from the Linux man page:
The free() function frees the memory space pointed to by ptr, which
must have been returned by a previous call to malloc(), calloc() or
realloc(). Otherwise, or if free(ptr) has already been called before,
undefined behavior occurs. If ptr is NULL, no operation is performed.
That word undefined is key. That means that it will not necessarily crash. Those are the worst kind of errors to debug - you are much better having a bug that crashes reliably every time. This may be safe for some configurations of compiler and libraries, but it is not for all of them. The method is best avoided.

Why my dangling pointer doesn't cause a segmentation fault?

My code:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int *p = (int *)malloc(sizeof(int));
free(p);
*p = 42;
return 0;
}
I created a pointer, then I pointed it to allocated space and finally I had assigned 42 to it.
In my opinion it should not work, it should cause a segmentation fault, but it works.
So, why?
PS: I normally compiled it with Gcc on Linux
Pure luck. The behavior in this case is undefined. I.e.: no expectations can be made as to what may happen.
In my opinion it should not work [...] but it works.
Don't worry, it doesn't work.
it should cause a segmentation fault
Tell that to the C standards committee. It's just undefined behavior, it isn't required to crash.
The more elaborate answer beyond "undefined" is that you can write to arbitrary memory locations in C as long as you stay within the processes allocated memory areas. Depending on OS, overwriting code may be allowed or not. The ill effects only turn up, once some other code of your process gets confused by what is found at the garbled memory location. Since your program exits right away after messing up the memory, the chance for some of its code to get confused is obviously small.
The behavior in this case is undefined ,
it is a possibility with undefin behavior
you display the memory address of p before and after free to check "p" with :
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int *p = (int *)malloc(sizeof(int));
printf("before \n %p \n",p);
free(p);
*p = 42;
printf("after\n %p \n",p);
printf(" %d \n",*p);
return 0;
}
before and after free we have the same address memory because free() don't assign NULL to p pointer, so *p = 42; work like static assignment although it's undefined behaviour.
suggest to use the FREE macro :
#define FREE(X) \
free(X);\
X=NULL;
test with this macro and you will see the expected behaviour

why dereferencing a C pointer after "free" gives value 0 [duplicate]

This question already has answers here:
Why do I get different results when I dereference a pointer after freeing it?
(7 answers)
Closed 9 years ago.
Below is the code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *p;
p=(int *)malloc(sizeof(int));
*p=5;
printf("Before freeing=%p\n",p);
printf("Value of p=%d\n",*p);
//making it dangling pointer
free(p);
printf("After freeing =%p\n",p);
printf("Value of p=%d\n",*p);
return 0;
}
Below is the output:
Before freeing=0x1485010
Value of p=5
After freeing =0x1485010
Value of p=0
After freeing the pointer, dereferencing gives the output "0"(zero).
Below is another code that also gives '0'
include <stdio.h>
#include <stdlib.h>
int main()
{
int *p;
p=(int *)malloc(sizeof(int));
printf("Before freeing=%p\n",(void *)p);
printf("Value of p=%d\n",*p);
return 0;
}
In this i have not freed the memory , just allocated it , still it gives '0' .
Is it like the default value of every uninitialized pointer is '0'??
why is it so ?
Don't rely on this, it's undefined behaviour. free() doesn't have to set the pointer to zero, this is just what your current implementation is doing for you. If you want to be 100% sure, regardless of your compiler, platform, etc. set your pointer to NULL after freeing it.
This is simply undefined behavior if we look at the C99 draft standard Annex J.2 which covers undefined behavior says:
The behavior is undefined in the following circumstances:
and included the following bullet:
The value of a pointer that refers to space deallocated by a call to the free or
realloc function is used (7.20.3).
Setting a pointer to NULL after free'ing is usually a good idea and you can find a good discussion here on that topic.
Dereferencing an invalid pointer leads to undefined results per spec. It's not guaranteed to fail.
While the answers "it doesn't matter, it is UB" are in general sufficient, one might be curious why the value changes. Curiosity is (IMHO) a valid reason to know the reason of why something happens.
It depends on the memory management which might decide to store addresses of the "next free block" or whatever in a freed memory area.
So what you observe is probably an action of the memory management.
For example, the memory management MIGHT be implemented in that way that it manages two linked lists and an upper pointer. One linked list contains the allocated memory chunks, pointing maybe 8 or 16 bytes before the "really usable" memory, and the other linked list points to the first free chunk, which in turn contains a pointer to the next one. The memory above the upper pointer is considered as free.
If you free the first memory block, the free list pointer points to it, and its first pointer sized data is zeroed, meaning that there is no other freed block. And there is your reason why the memory is zeroed out.
It is nice to know that things like these exist and how they work, but refrain the temptation to make use of that knowledge in production programs. One day they may fall onto your feet...

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