Can I free memory originally allocated from another pointer? - c

If I allocated memory from another pointer, then declare a pointer equal to the other pointer, can I then free the memory allocated with the first pointer by using free() on the new pointer?
Example:
typedef struct foo{
int n;
char c;
} foo;
foo* bar = malloc(sizeof(foo));
foo* tmp = bar; // declaring pointer identical to other pointer
free(tmp); // can I do this to free *bar?

Yes, it is completely fine.
Your implementation of malloc will most likely mark the chunk of memory as allocated before returning a pointer to it.
Now you can have as many pointer variables as you want which point to this chunk of memory and you can free that memory by calling free on any of them.
The pointer itself doesn't contain information about whether the memory it points to has been allocated. It just points to it.
int* i = malloc(sizeof(int) * 23);
int* j = i;
free(j);
// free(i); // this is undefined behavior, the memory was already freed

Yes you can do what you are asking about. But it is not another pointer, what you are freeing is the same pointer. When malloc returns a pointer, it is essentially giving you an integer that is the address of the start of the chunk of memory that it has reserved for you. When you are done are done with the memory, you pass that address to free. As far as free is concerned, there is no difference between:
free(malloc(17));
,
void *p = malloc(17);
free(p);
or
void *p1 = malloc(17);
void *p2 = p1;
free(p2);
In all of these cases the value returned from malloc is getting to free, and that is all that matters.

Related

Dangling pointers in C

When a pointer is allocated memory using malloc, pointer (say x)will now point to memory address.
Later I free this(x) memory pointer,but pointer is still pointing to it's old memory.
This would now create dangling pointer.
(Because I did not point the old pointer to NULL after free)
Now, assume I use malloc and assume new pointer(y) now points to same memory location as old pointer (x)
Doesn't memsetting new pointer (y) to 0 solve dangling pointer issue.
Assume I have only one struct type.So every malloc which I do is always of same size of same structure.
If it was different struct , I know i may still have some data at the end of struct if new pointer (y) has small memory allocation than pointer (x)
The term dangling pointer means that whatever address in memory it points to is invalid. If you make it valid, like your 2nd malloc, then the address becomes valid. If you store the same address in two different variables (via your assumption) both are valid pointers:
#include <stdio.h>
#include <stdlib.h>
struct s { int i; };
int main() {
struct s *p = malloc(sizeof(struct s));
printf("before: %p\n", (void *) p);
free(p);
// p is dangling
printf("after: %p\n", p);
struct s *p2 = malloc(sizeof(struct s));
// p and p2 are valid
printf("before: %p\n", (void *) p2);
free(p2);
// p and p2 are dangling
printf("after: %p\n", p2);
}
and the output from my pleasingly corroborative malloc:
before: 0x561b73d3b260
after: 0x561b73d3b260
before: 0x561b73d3b260
after: 0x561b73d3b260
Dangling pointers are only a concern if you try to use them after you've freed them.
Yes, it's possible that a new allocation can return the same address that x has. But you can never know whether this is going to happen, so you still can't use x any more. It would just be a coincidence if its address became valid again.
Even if you keep allocating and freeing the same size, there's no expectation that it will keep reusing the same address.
For safety you must assume that a freed pointer will never become valid again.

Using free on structure which contains unintialized pointer

I have structure with an integer and character pointer. I am just allocation memory for the structure. Now if try to free the same structure, pointer will also be freed?
struct a
{
int b;
char *c
};
main()
{
struct *d = malloc(sizeof(a));
free(d);
}
There is no memory leak in above programm?
In order for there to be a memory leak, there has to be something that was allocated that can no longer be referenced. Since the only thing allocated here is what was explicitly freed, there was no leak.
The fact that you have a pointer in the structure is irrelevant, since you never allocated anything for it to point to.

Does this specific code contain memory leakage?

int* a = (int*)malloc(5);
int* b = a;
free(b);
Is there memory leakage? If so, why does this occur?
This doesn't leak memory, you free what you allocate, but both a and b are invalid after the free so using either of them is undefined behaviour.
No, this is perfectly safe. (Though you shouldn't cast malloc(). Casts are evil and should be avoided whenever possible. malloc() returns void *, which you never need to cast to a different pointer type)
In your case, there is no memory leakage but these pointers are called Dangling pointers.
Because you are delete object from memory but pointers still pointing same memory location.
{
int* a = (int*)malloc(5);
int* b = a;
free(b); // a and b dangling now
a = b = NULL; //reset pointers // a and b are no longer dangling
}

malloc allocate memory to a non-pointer type

How to allocate memory to a type which is not a pointer ?
I'd searched on the Internet and my textbook then got nothing about this.
All the example come from those like that
char *test;
test = malloc (STRING_SIZE * sizeof (char));
Which in pointer form, but what if a structure don't even need a pointer type to do that job as follow
struct _test_t {
char *name;
int flag; // <-- Here
};
or this is deprecated ?
What I can do is only declare as a pointer
...
int *flag;
...
then allocate as usual ?
struct _test_t *t;
t->flag = malloc (sizeof (int));
or any way out ?
You seem to have some confusion about pointers and where things end up in memory. The fields of a struct are part of the struct's memory. In your case, the struct consists of a char pointer and an int. You don't need to allocate those separately once you have an instance of the struct, because they are already part of the struct.
struct _test_t *t = malloc(sizeof(struct _test_t));
t->flag = 123;
t->name = NULL;
Note that name doesn't point to anything interesting yet. Let's change that:
t->name = malloc(100);
Note the distinction between the pointer name and the memory that it points to. Only the pointer itself is part of the struct.
It is also possible to create an instance of the struct without using malloc, by allocating it on the stack:
struct _test_t t;
t.flag = 123;
t.name = malloc(100);
t is now allocated on the stack and will automatically be freed again when you leave the scope that it was declared in. However, name still points to memory on the heap which does not get freed with the struct, so you'd have to free that manually once you no longer need it.
Edit: You mention that you want to allocate memory to something that is not a pointer. That doesn't really make sense to me though. The function of malloc is to reserve some memory for your use and return a pointer to that memory. It needs to return the address of the memory that it has allocated because otherwise you wouldn't know where it is. And a pointer is really just an address value.
You can allocate space for an int with malloc, but you will get a pointer to an int that you have to use to access the actual int:
int *i = malloc(sizeof(int));
*i = 123;
In C, there is no way to refer to that int directly without going through a pointer, which might be what you want. In C++ you could use a reference to refer to the int value directly:
int *i = (int*)malloc(sizeof(int));
*i = 123;
int &j = *i;
cout << j << endl;
This would print "123", showing that j directly refers to the integer value. However, C does not have that feature, so you will always have to use the pointer.
malloc is used to allocate memory for objects whose size is not known at compile-time. That's why it returns a pointer, since it's the C representation for addresses (here of the memory area allocated on the heap).
Using malloc for another type does not make any sense, since their size are known (apart from templates but that's C++). Your _test_t struct (resp struct _test_t *t) is allocated resp. on the stack or the heap when declared, no need for you to manually allocate each members.

Exact output of free() in C?

I wanted to ask, if I have a pointer pointing at some struct, but then I free(struct) then if I dereference the pointer, will it be pointing to NULL? As in can I check, pointer != NULL or is this undefined?
Thanks!
Calling free() on the pointer does not change the pointer value. It will still point to the same memory that no longer belongs to your application. You should always assign NULL to a free'd pointer immediately after you free it to ensure that you don't use it again.
void *p = malloc(10); // p points to allocated memory
free(p); // p still points to invalid memory
p = NULL; // good practice
Consider the below code
int main()
{
int *p = (int *)malloc(sizeof(int) * 10);
free(p);
}
Here variable p is a local variable of a function main. Size of this variable will be 4 bytes(in 32bit m/c) or 8 bytes(in 64 bit m/c). Now we are allocating memory for storing 10 integer elements and that address is stored in variable p. Now we are calling free function to which we are passing the dynamic memory address which is stored in the local variable p. Now free function will free the memory and it will not be able to assign NULL to the variable p. Because we passed address as value, not reference to the pointer.
We can define a wrapper function for free like below
void myfree(void **p)
{
free(*p);
*p = NULL;
}
int main()
{
int *p = (int *)malloc(sizeof(int) * 10);
myfree(&p);
}
Or we can define macro function also
#define MYFREE(x) \
free(x); \
x = NULL;
It's undefined. C does not define what it does with the contents of the pointer, although most implementations do nothing.
Take a look at this page.
It clearly says:
Notice that this function leaves the value of ptr unchanged, hence it
still points to the same (now invalid) location, and not to the null
pointer.
Note that it is up to you to make sure that pointer is not dereferenced after being freed.

Resources