Freeing memory allocated to an array of void pointers - c++

I am declaring an array of void pointers. Each of which points to a value of arbitary type.
void **values; // Array of void pointers to each value of arbitary type
Initializing values as follows:
values = (void**)calloc(3,sizeof(void*));
//can initialize values as: values = new void* [3];
int ival = 1;
float fval = 2.0;
char* str = "word";
values[0] = (void*)new int(ival);
values[1] = (void*)new float(fval);
values[2] = (void*)str;
//Trying to Clear the memory allocated
free(*values);
//Error: *** glibc detected *** simpleSQL: free(): invalid pointer: 0x080611b4
//Core dumped
delete[] values*;
//warning: deleting 'void*' is undefined
//Similar Error.
Now how do I free/delete the memory allocated for values ( the array of void pointers)?

I suspect the issue is with the way that you allocated values: values = (void*)calloc(3,sizeof(void)). That should be sizeof(void *) rather than just sizeof(void).
sizeof(void) may be zero or something else that makes no sense, so you're not really allocating any memory to begin with... it's just dumb luck that the assignments work, and then the error pops up when you try to deallocate the memory.
EDIT: You're also asking for trouble by alternating between C++-style new/delete with C-style malloc/free. It is okay to use them both as long as you don't delete something you malloc'ed or free something you new'ed, but you're going to mix them up in your head if you go like this.

You have 3 things that are dynamically allocated that need to be freed in 2 different ways:
delete reinterpret_cast<int*>( values[0]);
delete reinterpret_cast<float*>( values[1]);
free( values); // I'm not sure why this would have failed in your example,
// but it would have leaked the 2 items that you allocated
// with new
Note that since str is not dynamically allocated it should not (actually cannot) be freed.
A couple of notes:
I'm assuming that the sizeof(void)
was meant to be sizeof(void*)
since what you have won't compile
I'm not going to say anything about
your seemingly random casting except
that it looks like code that ready
for disaster in general

This is the perfect situation for the boost::any class
Also you may want to consider using a vector rather than allocating your own memory.
std::vector<boost::any> data;
boost::any i1 = 1; // add integer
data.push_back(i1);
boost::any f1 = 1.0; // add double
data.push_back(f1);
data.push_back("PLOP"); // add a char *
std:: cout << boost::any_cast<int>(data[0]) + boost::any_cast<double>(data[1])
<< std::endl;
Going back to your original code the main problem was:
values = (void*)calloc(3,sizeof(void));
// This should have been
void** values = (void**)calloc(3,sizeof(void*));
// Freeing the members needs care as you need to cast them
// back to the correct type before you release the memory.
// now you can free the array with
free(values);
Also note: Though it is not illegal to use both new/delete and calloc/free in the same piece of code it is frowned upon. Mainly because it is easy to get things mixed up and that could potentially be fatal.

You're mixing new and *alloc(). That's a no-no, and can lead to undefined results.

I'm not sure why you are using new if you're doing things in C (referencing the tag here).
I would malloc the individual pieces of the array I need and then free them when I'm done I suppose. You can't free something you didn't first malloc. You also can't delete a void pointer.

Note that you're also not deleting values[0] and values[1] which is a memory leak, Yet by your design you can't free values[2] since its a pointer into you .data section.

You'd have to keep track of how many void* were originally calloc'd, and iterate over them, free-ing each one, then free the original values variable.
darn formatting... (the preview is working fine).
int ct = 3;
values = (void*)calloc(ct,sizeof(void));
//can initialize values as: values = new void* [3];
int ival = 1;
float fval = 2.0;
char* str = "word";
values[0] = (void*)new int(ival);
values[1] = (void*)new float(fval);
values[2] = (void*)str;
for ( int i = 0; i < ct; i++ ) [
delete( values[i] );
}
free( values );

Related

Malloc of pointer to an array- C++

I have a function which gets as a parameter a pointer to array,
e.g. int** segs.
I need to allocate (in the function-body) memory for the array, which has size 100 for example.
My attempt was:
*segs=(int*)(malloc(100));
So far so good.
I put a value into *segs[0], and still everything is great.
But... when I try to reach *segs[1], I get an "invalid write of size 4" error from valgrind, which leads to seg-fault.
I have no idea why does that happen.
I tried to reach to *segs[2], but then I get even something weirder-
Error of uninitialised value of size 8.
Due to operator precedence, *segs[N] is treated as *(segs[N]), which is ok when N is equal to 0. However, when you do the same thing using the index 1, things break since nothing has been allocated for segs[1]
For any index other than zero, you need to use (*segs)[N].
It will be easier to use a temporary pointer in the function.
int* ptr = (int*)(malloc(100));
*segs = ptr;
// and then
ptr[0] = ...; // Good
ptr[1] = ...; // Good
...
ptr[99] = ...; // Still good
Upgrading to C++ Way
Pass the pointer by reference.
void foo(int*& segs) { ... }
Use new instead of malloc to allocate memory.
segs = new int[100];
Better yet, use std::vector insteady raw arrays.
void foo(std::vector<int>& segs) { ... }

Difference between creating a pointer with 'new' and without 'new' apart from memory allocation?

What is the difference between these pointers?
I know that this one is going to be stored on the heap, even though a pointer is only 8 bytes anyways, so the memory is not important for me.
int* aa = new int;
aa = nullptr;
and this one is going to be stored on the stack.
int* bb = nullptr;
They both seem to work the same in my program. Is there any difference apart from memory allocation? I have a feeling that the second one is bad for some reason.
2) Another question which is somewhat related:
Does creating a pointer like that actually take more memory? If we take a look at the first snippet, it creates an int somewhere (4 bytes) and then creates a pointer to it (8 bytes), so is it 12 bytes in total? If yes are they both in the heap then? I can do this, so it means an int exists:
*aa = 20;
Pointers are integers that just indicate a memory position, and a type (so they can only point to variables of that type).
So in your examples, all pointers are stored in the stack (unless they are global variables, but that is another question). What they are pointing to is in the heap, as in the next example.
void foo()
{
int * ptr = new int(42);
// more things...
delete ptr;
}
You can have a pointer pointing into the stack, for example, this way:
void foo()
{
int x = 5;
int * ptr = &x;
// more things...
}
The '&' operator obtains the memory position of the variable x in the example above.
nullptr is the typed equivalent to old NULL. They are a way to initialize a pointer to a known and secure value, meaning that they are not pointing to anything else, and that you can compare whether they are NULL or not.
The program will accept pointers pointing to the stack or the heap: it does not matter.
void addFive(int * x)
{
*x += 5;
}
void foo()
{
int x = 5;
int * ptr1 = &x;
int * ptr2 = new int(42);
addFive( ptr1 );
addFive( ptr2 );
addFive( &x );
printf( "%d\n", *ptr1 );
printf( "%d\n", *ptr2 );
// more things...
delete ptr2;
}
The only difference is that the C runtime will keep structures telling how much memory has been spent in the heap, and therefore storing variables in the heap comes at a cost in performance. On the other hand, the stack is always limited to a fixed amount of memory (relatively small), while the heap is much larger, allowing you to store big arrays, for example.
You could take a look at C-Sim, which simulates memory in C (disclaimer: I wrote it).
Hope this helps.

Pointer being freed was not allocated with realloc and malloc in construct function

I tried dataPoolBuffer = realloc(dataPoolBuffer, sizeof(char)*(dataPoolSize)); already, but Xcode reports:assigning to 'char *' from imcompatible type 'void'.
I create a class:
class solutionBuffer{
private:
char * dataPoolBuffer;
char * consumerBuffer;
char * flagBuffer;
int dataPoolSize;
int consumerBufferSize;
mutex safe;
public:
solutionBuffer(){
safe.lock();
dataPoolSize = 0;
consumerBufferSize = 0;
dataPoolBuffer = (char*)malloc(sizeof(char)*1);
consumerBuffer = (char*)malloc(sizeof(char)*1);
flagBuffer = (char*)malloc(sizeof(char)*1);
}
int add(char* data, int length)
{
dataPoolSize += length;
realloc(dataPoolBuffer, sizeof(char)*(dataPoolSize));
realloc(flagBuffer, sizeof(char)*(dataPoolSize));
memcpy(dataPoolBuffer + dataPoolSize - length, data, sizeof(char)*(length));
return 0;
}
~solutionBuffer(){
printf("%d",strlen(dataPoolBuffer));
free(dataPoolBuffer);
free(consumerBuffer);
free(flagBuffer);
safe.unlock();
}
};
Every time when we call .add function, it will realloc memory for the variable. However, when I do that in main():
char data[] = "0123456789";
char data2[] = "01234567890123456789";
solutionBuffer buffer;
buffer.add(data, 10);
buffer.add(data2, 20);
The xoce shows:pointer being freed was not allocated in ~solutionBuffer() when it was trying to free dataPoolBuffer .
Why it does like that? How to fix that ?
According to the documentation,
realloc(dataPoolBuffer, sizeof(char)*(dataPoolSize));
reallocates dataPoolBuffer, but doesn't change where dataPoolBuffer points. So odds are pretty good that dataPoolBuffer is now pointing to invalid memory.
dataPoolBuffer = (char*)realloc(dataPoolBuffer, sizeof(char)*(dataPoolSize));
will do you what you want, but rethink how you are doing this. You're setting yourself up for a lot of pain. Your class violates The Rule of Three, for one thing. std::vector will handle all of container resizing and memory management for you with no muss and no fuss.
When you call realloc(), you need to assign the result back to the pointer variable. realloc() often needs to move the memory to a new location, and it returns that location. Your code leaves the variable pointing to the old location, and you get undefined behavior when you try to use it after that.
So it should be:
dataPoolBuffer = (char*)realloc(dataPoolBuffer, sizeof(char)*(dataPoolSize));
flagBuffer = (char*)realloc(flagBuffer, sizeof(char)*(dataPoolSize));

delete[] and delete seems to behave alike

here if I use delete or delete[] the output is still 70. Can I know why?
#include<iostream>
using namespace std;
int main()
{
int* c = new int[100];
for(int i=0; i<98; i++)
{
c[i] = i;
}
cout<<c[70]<<endl;
delete[] c;
or
delete c;
cout<<c[70]<<endl; //outputs 70 even after delete[] or delete
return 0;
}
Accessing deleted memory is undefined behavior. Deleting with the wrong delete is also UB. Any further discussion is pointless in the sense that you cannot reliably expect any outcome.
In many cases, UB will just do the "correct" thing, but you need to be aware that this is completely "by chance" and could change with another compiler, another version of the same compiler, the weather... To get correct code, you need to avoid all cases of UB, even those that seemingly work.
Using new will just allocate some memory to your program and return a pointer pointing at the said memory address, reserving as much memory as needed for the datatype. When you use delete later, it "frees" the memory, but doesn't delete it's content. If you had an int with the value 70 stored at that address, it will still contain 70, until another application wants some memory, gets said address and puts another value in there.
If you use new to allocate memory for an array, you will reserve following blocks of memory until there are enough blocks for your specified array length.
Let's say you do the following:
int main() {
int* array = new int[10]; // array now points to the first block of the allocated memory
delete array; // since array points to the first block of the array, it will only free that block, but nothing else, causing a memory leak
delete[] array; // will free all memory allocated by the previous new
// Note that you should never free allocated memory twice, like in this code sample. Using delete on already freed memory is undefined behaviour!
]
Always use delete for single variables and delete[] for arrays.
A demonstration of your problem:
int main() {
int* c = new int[10]; // We allocate memory for an array of 10 ints
c[0] = 1; // We set the value of the first int inside the array to 1
delete[] c;
/*
* We free the previously allocated memory.
* Note that this does not delete the CONTENT of the memory!
* c does still point towards the first block of the array!
*/
std::cout << c[0];
/*
* Firstly, this is undefined behaviour (Accessing deallocated memory).
* However, this will output 1,
* unless some other process allocated the memory at the address
* and filled it with another value already. (Very unlikely)
*/
return 0;
}
If you want to delete / overwrite the content of the deleted memory, you can use std::memset.
Example:
#include <cstring>
int main() {
std::size_t length = 10;
int* c = new int[length];
c[0] = 1;
std::cout << c[0] << std::endl; // Will output 1
std::memset( c, 0, length ); // Fill the memory with 0 bytes
delete[] c; // Now we free the array's memory
std::cout << c[0] << std::endl; // Will output 0
}
As others pointed its undefined behaviour and anything can happen.
These can be easily caught with the help of tools like valgrind.

C++ what exactly does new <datatype>(<value>) do?

In this code:
int * p = new int(44);
p is allocated on the heap and the value it points to is 44;
but now I can also do something like this:
p[1] = 33;
without getting an error. I always thought
int * p = new int(44);
was just another way of saying "P is allocated on the heap and points to an address containing 44" but apparently it makes p a pointer to an array of ints? is the size of this new array 44? Or is this result unusual.
You were right: P is allocated on the heap and points to an address containing 44. There's no array allocated. p[1] = 33; is what they call "undefined behavior". Your program might crash, but it's not guaranteed to crash every single time you do this.
int *p_scalar = new int(5); //allocates an integer, set to 5.
If you access p_scalar[n] (n <> 0) it may crash
In your example, the C++ language gives you a default implementation for the subscript operator for pointers that looks somehow similar to this:
(*Ptr)& operator[](size_t index)
{
return *(address + index*sizeof(*Ptr));
}
This can always be overloaded and replaced for any type. Integers are not an exception, when you say:
int * pointer = alocate_int_array();
pointer[1] = 1;
You're using the compiler-augmented default implementation of that operator.