Free a void ** pointer - c

I'm writing code to free a generic double pointer in C (void **ptr). How do I check to see if the pointer was allocated via malloc/calloc? How do I free the internal pointers? (I learned to do this by using a for loop and being given the number of members in the pointer, but I am not given that here.). The function declaration is
void freeArray(void **ptr);
How would you go about freeing this pointer, and error checking to make sure you won't get a seg fault or memory leak or other memory error?

I'm writing code to free a generic double pointer in C (void **ptr).
I believe there is not such thing as a generic double pointer. A pointer is just that: a pointer.
How do I check to see if the pointer was allocated via malloc/calloc?
You do not. A pointer is not allocated. Memory is allocated and the address of the area is assigned to a pointer.
How do I free the internal pointers? (I learned to do this by using a
for loop and being given the number of members in the pointer, but I
am not given that here.). The function declaration is
void freeArray(void **ptr);
"Internal pointer" is not a great description for this use, I believe.
Anyway, compare your function prototype with the usual main() prototype
int main(int argc, char** argv)
and you will see something is missing here.
Maybe it is more clear if you write
void** ptr = NULL;
You are declaring ptr. As a pointer. But ptr is allocated by now. It is static. May be 4 may be 8 bytes. And it points to a pointer to void. Just this.
ptr is void**, *ptr is void*, **ptr is void. When using ptr as a block of pointers you must do the same as the system does with main(): build the block and keep your own argc, the count of values. It is your problem to do that, or better, it is you problem NOT to do that.
Try this:
void freeArray(int ptrc, void** ptr);
And keep this pair always together and updated, so the part of "being given the number of members in the pointer" is a no brainer.

There is no portable way to determine if ptr points to an allocated block or not, nor how large this block is, nor whether the pointers in this block are valid and point to allocated memory.
freeArray is given a pointer to an array of void pointers. Since there is no information about the number of pointers to free, an assumption must be made:
either the number of pointers is fixed. Say your program is dealing with arrays of 3 pointers everywhere, freeArray might be assumed to free 3 pointers...
or the array could be null terminated, such as the argv array passed to main. Note however that this particular array of strings is not meant to be freed this way.
Look at the code that allocates the arrays and determine which convention is used.
Here is a naive implementation of freeArray() for a null terminated allocated array of pointers to allocated blocks:
void freeArray(void **ptr) {
if (ptr) {
for (size_t i = 0; ptr[i]; i++) {
free(ptr[i]);
}
free(ptr);
}
}

freeing pointer does not change wether it's allocated using malloc or calloc, if you wanna free array of pointers you should know before length of it. unless you now that the last element of the array is NULL so you can loop and stop when encounter NULL.

Related

malloc function return pointer to an array right?

I have a doubt. When malloc() function returns a pointer, is it a pointer to a linear block of memory (similar to array)? Or is it something else?
I would like to know the structure of that memory.
I would like to know the structure of that memory.
There is no structure. Just the memory chunk
(similar to array?)
the memory chunk is exactly the same as array.
The difference is only that reference of that chunk is a pointer.
You cant use `sizeof operator to get the size of that memory chunk.
the reference of the pointer is not the same as reference to the memory chunk. (address of the array always give the reference to first element of the array)
A pointer only points to a single object of the pointed-to type (although that object may be an aggregate type) or function. That object may be the first object in a larger sequence like an array, but you can't know that from the pointer itself. Given code like
char x;
char *p1 = &x;
char *p2 = malloc( sizeof *p2 * 10 );
There's no way to know from the pointers themselves that p1 points to a single standalone object while p2 points to the first in a sequence of objects. You have to keep track of that information separately.
This is true for pointers to aggregate types like
char a[20];
char (*p3)[20] = &a;
char (*p4)[20] = malloc( sizeof *p4 * 10 );
Same deal as above - both p3 and p4 point to a single 20-element array of char. In p4's case, it's pointing to the first in a sequence of 20-element arrays of char, but again you can't know that from the value of p4 itself.
Note that malloc and calloc don't operate in terms of objects, they operate in terms of bytes - you tell them how many bytes of memory you want to reserve, but they have no idea what type of object or sequence of objects is going to occupy that memory. They also need some way to keep track of what's been allocated, so many implementations will reserve some extra memory on each allocation for bookkeeping purposes.
malloc function return pointer to an array right?
size_t n = ...;
void *p = malloc(n);
When the returned pointer is a null pointer, the allocation failed and the pointer should not be dereferenced. It does not need to be free'd.
if (p == NULL) Handle_Failure();
A successful void *malloc(size_t n) call does return a pointer, a void * that can be assigned to any object pointer type. A cast is not needed. p is not a pointer to an array, just a void *. The allocated memory can be the destination of a copy of any object including arrays.
my_type *p = malloc(n);
Use the pointer to store the contents of an array, int, or any object. As long as the initial allocation was big enough, it does not matter. The pointer meets the alignment requirements for all object types. When done, free it exactly once. Then do not use the value in the pointer. Yet p can be re-assigned.
int foo(const struct abc *x) {
struct abc *p = malloc(sizeof *p);
if (p == NULL) {
return 1;
}
*p = *x;
bar(p);
free(p);
return 0;
}
Allocation of 0 bytes is a special case and can be done. Should malloc() return a null pointer or not, the pointer should not be dereferenced. No *p.
Once code gets p, code does not have a portable way to get the size of memory allocated. Code should keep track of the original n as needed. malloc() uses a size_t argument.
Note: free(NULL) is OK
When malloc(); function returns a pointer is it a pointer to a linear blocks of memory
Yes, and it's a void pointer.
(similar to array).
No. It's not an array, or in other words, it's not the pointer to the first element of an array of size passed to malloc(). It's a memory region/ block, virtually contiguous, but the returned pointer (or the variable storing the return value) will not have properties of an array.
would like to know the structure of that memory
If you only want to use the returned memory location, you need not bother. You can just store the returned pointer to a variable of a pointer to complete type, and use that variable to perform operations (read from/ write to) that memory location.
It does not return pointer to an array.
malloc(size_t n) returns a pointer to a contiguous memory location specified by the parameter n.
Note that it is opposed to calloc(size_t nmem, size_t size) which initializes each bit to zero while malloc() leaves the value as indeterminate as suggested in comments.
Default value of malloc
Why malloc may be indeterminate from SO
More about calloc and malloc from SO

Freeing char[] in C gives error and how do C compiler handle that char[]

Although arrays are basically pointers, freeing char[] in C gives an error.
#include <stdlib.h>
int main(void) {
char ptr[] = "Hello World";
free(ptr); // this gives error at run time
}
ERROR: nexc(4212,0x10038e3c0) malloc: * error for object 0x7fff5fbff54c: pointer being freed was not allocated
* set a breakpoint in malloc_error_break to debug
The interesting part is that, it is saying I am freeing a pointer which is not allocated.
How could this happen?
But in C++, compiler gives me a compile time error instead.
int main(void) {
char ptr[] = "Hello World";
delete ptr; // this gives error at compile time
}
like,
Cannot delete expression of type char[12]
I thought this is because of compiler handles the char[12] by allocating when the function is called and deallocating the memory when the function ends. So, I write some codes after free(ptr); before the function ends.
#include <stdlib.h>
int main(void) {
char ptr[] = "Hello World";
free(ptr); // this still gives error at run time
printf("\n");
printf("\n");
printf("\n");
printf("\n");
printf("\n");
}
This still gives error. How is this happening?
You only free what you have allocated using malloc (directly or indirectly) or related function (like realloc).
Attempting to pass a pointer not returned by malloc will lead to undefined behavior.
That you get a compiler error for delete in C++ is first and foremost because C and C++ are different languages with different rules.
And remember, an array is an array, not a pointer. Though an array can decay to a pointer to its first element in many situation (like when passing it to a function).
You only call free on dynamic memory that you've allocated using malloc, calloc &c.. Similarly, you only call delete on memory allocated with new. In your case, the C++ compiler is required to issue a diagnostic since pointer decay is not permitted to occur in this particular instance, and delete requires a pointer type.
The behaviour on attempting to call free on automatic memory is undefined.
You only need to free what was malloced.
Your ptr is not a pointer, it is an array; an automatic local (inside main()) variable. It does not need freeing and attempting to free it is a mistake.
All the static Strings will be allocated in the data section. You can't free data from this section. Threrefore, you can free only data the you have allocated with malloc (calloc / ralloc)
in C programming language, you cannot write the instruction you made for obvious reasons. First of all, it must be understood that a pointer variable is a variable like so many others with a type except that it contains only addresses, so it is called a pointer variable because it contains the address of what is in memory. A pointer is therefore an address associated with a type of data and these two elements are inseparable.
If the pointer variable contains the address of an object of the whole type, the pointed object is used to know how to interpret the bits that make up this object, as well as its size. The instruction you wrote is therefore a constant pointer to a character type stored somewhere in memory. The string is therefore probably placed in a read-only data segment and therefore you cannot modify the string or release its memory, because the pointer variable does not point to a string in a space allocated dynamically beforehand by the "malloc" or "calloc" allocation function, and that is why you have the error message.
The second error is due to a confusion of your part here too, you must understand that there is a difference between an array of characters and a pointer. In simpler terms, a pointer variable is not an array and an array is not a pointer, but access to the element is done in the same way. For an array, the characters that make up the string and end with "\0" can be changed, but the array of characters will always point to the same address in memory and the pointer can contain another address, but beware, if you allocate the memory with a pointer and then point to other pars without releasing the memory you allocated creates a memory leak.
This is the proper way of using delete ! you first have to let the compiler know that the variable ptr is dynamic by using new!
#include<iostream>
#include<new>
using namespace std;
int main(void) {
char *ptr;
try{
ptr = new char [20];
} catch(bad_alloc xa){
cout<<"error";
}
ptr= "Hello World";
cout<<ptr;
delete [] ptr;
}

(int*) when dynamically allocating array of ints in c

So I'm a bit confused on how to make a function that will return a pointer to an array of ints in C. I understand that you cannot do:
int* myFunction() {
int myInt[aDefinedSize];
return myInt; }
because this is returning a pointer to a local variable.
So, I thought about this:
int* myFunction(){
int* myInt = (int) malloc(aDefinedSize * sizeof(int));
return myInt; }
This gives the error: warning cast from pointer to integer of different size
This implies to use this, which works:
int* myFunction(){
int* myInt = (int*) malloc(aDefinedSize * sizeof(int));
return myInt; }
What I'm confused by though is this:
the (int*) before the malloc was explained to me to do this: it tells the compiler what the datatype of the memory being allocated is. This is then used when, for example, you are stepping through the array and the compiler needs to know how many bytes to increment by.
So, if this explanation I was given is correct, isn't memory being allocated for aDefinedSize number of pointers to ints, not actually ints? Thus, isnt myInt a pointer to an array of pointers to ints?
Some help in understanding this would be wonderful. Thanks!!
So, if this explanation I was given is correct, isn't memory being allocated for aDefinedSize number of pointers to ints, not actually ints?
No, you asked malloc for aDefinedSize * sizeof(int) bytes, not
aDefinedSize * sizeof(int *) bytes. That's the size of memory you get, the type depends on the pointer used to access the memory.
Thus, isnt myInt a pointer to an array of pointers to ints?
No, since you defined it as a int *, a pointer-to-an-int.
Of course the pointer has no knowledge of how large the allocated memory are is, but only points at the first int that fits there. It's up to you as programmer to keep track of the size.
Note that you shouldn't use that explicit typecast. malloc returns a void *, that can be silently assigned to any pointer, as in here:
int* myInt = malloc(aDefinedSize * sizeof(int));
Arithmetic on the pointer works in strides of the pointed-to type, i.e. with int *p, p[3] is the same as *(p+3), which means roughly "go to p, go forward three times sizeof(int) in bytes, and access that location".
int **q would be a pointer-to-a-pointer-to-an-int, and might point to an array of pointers.
malloc allocates an array of bytes and returns void* pointing to the first byte. Or NULL if the allocation failed.
To treat this array as an array of a different data type, the pointer must be cast to that data type.
In C, void* implicitly casts to any data pointer type, so no explicit cast is required:
int* allocateIntArray(unsigned number_of_elements) {
int* int_array = malloc(number_of_elements * sizeof(int)); // <--- no cast is required here.
return int_array;
}
Arrays in C
In C, you want to remember that an array is just an address in memory, plus a length and an object type. When you pass it as an argument to a function or a return value from a function, the length gets forgotten and it’s treated interchangeably with the address of the first element. This has led to a lot of security bugs in programs that either read or write past the end of a buffer.
The name of an array automatically converts to the address of its first element in most contexts, so you can for example pass either arrays or pointers to memmove(), but there are a few exceptions where the fact it also has a length matters. The sizeof() operator on an array is the number of bytes in the array, but sizeof() a pointer is the size of a pointer variable. So if we declare int a[SIZE];, sizeof(a) is the same as sizeof(int)*(size_t)(SIZE), whereas sizeof(&a[0]) is the same as sizeof(int*). Another important one is that the compiler can often tell at compile time if an array access is out of bounds, whereas it does not know which accesses to a pointer are safe.
How to Return an Array
If you want to return a pointer to the same, static array, and it’s fine that you’ll get the same array each time you call the function, you can do this:
#define ARRAY_SIZE 32U
int* get_static_array(void)
{
static int the_array[ARRAY_SIZE];
return the_array;
}
You must not call free() on a static array.
If you want to create a dynamic array, you can do something like this, although it is a contrived example:
#include <stdlib.h>
int* make_dynamic_array(size_t n)
// Returns an array that you must free with free().
{
return calloc( n, sizeof(int) );
}
The dynamic array must be freed with free() when you no longer need it, or the program will leak memory.
Practical Advice
For anything that simple, you would actually write:
int * const p = calloc( n, sizeof(int) );
Unless for some reason the array pointer would change, such as:
int* p = calloc( n, sizeof(int) );
/* ... */
p = realloc( p, new_size );
I would recommend calloc() over malloc() as a general rule, because it initializes the block of memory to zeroes, and malloc() leaves the contents unspecified. That means, if you have a bug where you read uninitialized memory, using calloc() will always give you predictable, reproducible results, and using malloc() could give you different undefined behavior each time. In particular, if you allocate a pointer and then dereference it on an implementation where 0 is a trap value for pointers (like typical desktop CPUs), a pointer created by calloc() will always give you a segfault immediately, while a garbage pointer created by malloc() might appear to work, but corrupt any part of memory. That kind of bug is a lot harder to track down. It’s also easier to see in the debugger that memory is or is not zeroed out than whether an arbitrary value is valid or garbage.
Further Discussion
In the comments, one person objects to some of the terminology I used. In particular, C++ offers a few different kinds of ways to return a reference to an array that preserve more information about its type, for example:
#include <array>
#include <cstdlib>
using std::size_t;
constexpr size_t size = 16U;
using int_array = int[size];
int_array& get_static_array()
{
static int the_array[size];
return the_array;
}
std::array<int, size>& get_static_std_array()
{
static std::array<int, size> the_array;
return the_array;
}
So, one commenter (if I understand correctly) objects that the phrase “return an array” should only refer to this kind of function. I use the phrase more broadly than that, but I hope that clarifies what happens when you return the_array; in C. You get back a pointer. The relevance to you is that you lose the information about the size of the array, which makes it very easy to write security bugs in C that read or write past the block of memory allocated for an array.
There was also some kind of objection that I shouldn’t have told you that using calloc() instead of malloc() to dynamically allocate structures and arrays that contain pointers will make almost all modern CPUs segfault if you dereference those pointers before you initialize them. For the record: this is not true of absolutely all CPUs, so it’s not portable behavior. Some CPUs will not trap. Some old mainframes will trap on a special pointer value other than zero. However, it’s come in very handy when I’ve coded on a desktop or workstation. Even if you’re running on one of the exceptions, at least your pointers will have the same value each time, which should make the bug more reproducible, and when you debug and look at the pointer, it will be immediately obvious that it’s zero, whereas it will not be immediately obvious that a pointer is garbage.

Why do malloc and free have different return types?

Declarations look like these:
void *malloc(size_t size);
void free(void *pointer)
As far as I can understand, the void *malloc means that malloc returns a pointer to void ("Void pointer") and free is just void. What's the difference? Why does it look this way?
The void just means the return type isn't defined (not a pointer to a char, for example), just a contiguous block of memory of specified size.
free() doesn't return anything. It doesn't need to.
malloc returns a pointer (void*) to the allocated memory. free frees the memory. It doesn't return anything (void).
They are not equivalent to each other. Why compare?
malloc allocates memory so it should return the pointer to the aloocated memory.
free deallocates the memory and it doesn't have to return any value, so it's void.
void pointer is generic pointer. This can be assigned to any type of pointer. so malloc is designed in such that way.
free() is not going to return anything. simply de-allocates the block of memory with given address entry from heap.
The problem with C is that in this case, it is weakly typed. You cannot malloc an array of ints, chars, doubles, or any other struct - there would have to be a malloc/free pair for any type possible (including your own structs). So instead of returning a pointer to some type, the pointer has the void type. That means, the type of the data is undetermined, and you usualy cast that pointer to the type pointer you need.
The common usage pattern of malloc therefore is:
type *myMemory = (type *)malloc(x * sizeof(type));
where type is the type you want to malloc (int, char, struct...) and x is the number of "instances"you want to malloc.
The free method just takes the pointer from malloc and frees it. Following the same logic, it cannot take an int, char... pointer, so it takes void pointer. Void pointer is "compatible" with any other pointer.
They are completely differet things. The fact that they look similar is just down to the syntax used.
"void *" is a pointer to a block of memory without any particular type associated with it. You can cast it to any other pointer type.
"void" (without the star) means that the function doesn't return any value at all.
malloc() is a memory allocation function which primary job is to return pointer to starting address of the memory block allocated by malloc() .The problem is that malloc() is designed to be generic not for the any single type so,the address return should not be for a specific type (e.g char,int) ,it should be generic so malloc() returned a void pointer which is giving an option to programmer to cast it to any type and use that memory. so its return type is void *.
For free(),it a memory freeing function which primary job is to free the content of the memory address pointed by the argument,This also designed for generic by which it can able to free any memory type not for only char,int etc.so its argument type is void *.
free returning nothing means that is a void not any pointer or any thing else,so it simply void.
void* means "any type pointer". Points to memory which type is not defined or not important at that particular moment.
void is plain nothing. No value.
printf("malloc returned address %p\n", malloc(1)); is valid C, malloc returns a pointer to a block of memory containing undefined data.
printf("free returned status %d\n",free(ptr)); is not valid C because free does not actually return anything.

realloc() Failure

I was trying to implement a simple function that can concatenate any number of strings passed to it. My call to realloc fails. Is it something to do with the fact that the string arguments that i pass to the function are stored in data segment where as realloc looks to allocate memory from the heap ? This is just an idea i have. I'm a beginner so please excuse if it seems stupid. How can i make this function run ?
//Program to implement a function that can concatenate any number of argumnets
#include<stdio.h>
#include<stdarg.h>
#include<string.h>
#include<stdlib.h>
char *mstrcat(char *first, ...);
int main(int argc, int **argv){
char *s;
s=mstrcat("I ","Love ","Stack","Overflow");
printf("%s\n",s);
}
char *mstrcat(char *first, ...){
char *s=first,*p;
int len=0; // stores the length of the string as it grows
len=strlen(s);
va_list aptr; // creates a pointer to the unnamed argument list
va_start(aptr,first); // initialise aptr to the first unnamed argument
if(aptr==NULL){
return s;
}
while((p=va_arg(aptr,char *))!=NULL){ // till there are no more arguments to process
len+=strlen(p);
if((s=(char *)realloc(s,len+1))!=NULL){
strcat(s,p);
}
else{
printf("Failed to concatenate\n");
return first;
}
}
return s;
}
Your code has an Undefined Behavior. The standard mandates that the pointer being passed to realloc should exactly match the pointer which was allocated dynamic memory using a memory management function. Memory management functions specified by the standard are:
aligned_alloc, calloc, malloc, and realloc.
The pointer you are passing to realloc() was not returned by any of these and hence the Undefined Behavior.
Reference:
c99 standard: 7.22.3.5 The realloc function
Synopsis: #1
#include <stdlib.h>
void *realloc(void *ptr, size_t size);
#3
If ptr is a null pointer, the realloc function behaves like the malloc function for the
specified size. Otherwise, if ptr does not match a pointer earlier returned by a memory
management function, or if the space has been deallocated by a call to the free or
realloc function, the behavior is undefined. If memory for the new object cannot be
allocated, the old object is not deallocated and its value is unchanged.
A point about realloc, the size argument is new size of the allocated data, which for you should be the old length of s plus the length of p (+1 for the terminator of course).
And as you suspect, you can not use the first string as the base of the reallocations. Instead set s to NULL at the start of the function.
You are passing string literals to your mstrcat function, and they are probably stored in a read-only area of the process, which means that they cannot be modified or resized.
realloc can only be used with a pointer previously returned by malloc or realloc. Other kinds of uses (as is yours) yield undefined behaviour.
the mstrcat function is starting with s pointing to the first argument. Then you are trying to realloc() this pointer which is a static string. This will not work. You can only realloc a pointer previously allocated by malloc().
I suggest you change char *s=first to char *s=strdup(first) to allocate a copy of the first argument, and then this code should work.
The concatenation algorithm is pretty inefficient, but that's another story... (hint: you may want to enumerate the arguments and keep track of the total size, then alloc() a corresponding buffer and then concatenate all the arguments into it)

Resources