passing objects into function through void pointer - c++

I am writing a simple Memory Manager. I am trying to simplify this function so others can
just add the object they want to allocate as the first parameter. The Memory Manager will
allocate the space for that object, and set the object's pointer to point to the allocated
space. Problem is I'm not sure how to go about making the parameter so just about any type
of object can be passed in, without having to cast it like crazy to get it to work.
Here is the function:
bool MemoryManager::Allocate(void** data, unsigned int allocSize, bool isArray)
{
if((m_Heap.m_Pool == nullptr) || (*data != NULL))
return false;
if(isArray)
allocSize += sizeof(unsigned int) * 4;
void* mem = m_Heap.Allocate(allocSize);
if(mem)
{
*data = mem;
return true;
}
else
return false;
}
This is currently how I have to call it to get it to work:
int* Test = NULL;
MemoryManager::GetInstance()->Allocate((void**)(&Test), sizeof(int), false);
Any help or guidance would be greatly appreciated! :)

Using templates and overloading, you can operate directly on the type of data, including its size:
template<typename T>
bool MemoryManager::Allocate(T*& data)
{
size_t allocSize = sizeof(T);
...
}
When it comes to arrays though, normally we try to steer clear of pointers in C++. Use vector<T> for example. You can specify your own allocator.
I would consider whether you even want to return a raw pointer in fact; you might consider returning a smart pointer object.
Your array size calculation is flawed; I am not really sure what you're trying to do there. I would expect that allocSize is really element size, and thus the calculation is:
allocSize = (allocSize * elementCount);
But you don't have any way to know how many elements the user is requesting.

Related

Why don't my simple code work in C++?

Error in function realloc(): invalid pointer
int indZero = 0;
int *perZero=NULL;
int zero = 0;//Initialization
ProcessBit(zero,&indZero,&perZero);// Call function
void ProcessBit(int num,int *ind,int **mas)
{
mas=(int**)realloc(&mas,((*ind))*sizeof(int));// Error
mas[num-1]++;//it's correct line
}
A few problems:
The first argument to realloc is the original pointer (or NULL).
Your ProcessBit doesn't really emulate pass-by-reference correctly.
You can use a negative index.
mas is a pointer to a pointer to int, but you use it as a pointer to int.
A "fixed" version might look something like this:
void ProcessBit(int num, int *ind, int **mas)
{
int *temp = realloc(*mas, (*ind + 1) * sizeof(int));
if (temp == NULL)
{
// TODO: Handle error
// TODO: return or exit(EXIT_FAILURE)
}
*mas = temp;
(*mas)[*ind] = 0; // Initial initialization
if (num > 0)
{
(*mas)[num - 1]++;
}
++*ind; // Increase the size
}
Now, if this really was C++ (as you tagged your question) then you should be using std::vector instead, which would solve almost all your problems with much simpler code.
The parameters are wrong. Since you are trying to realloc a NULL pointer it should behave like malloc; however, the header declared in cstdlib is
void* realloc( void* ptr, std::size_t new_size );
The formal parameter mas is already the address of the pointer, so the call should be
*mas=(int*)realloc(*mas,((*ind))*sizeof(int));
(*mas)[num-1]++;
Since realloc handles and returns pointers by copy, not by reference.
You are passing the address of the memory location where the address of a memory location (NULL) is stored to your ProcessBit function, and then the address of that location to the realloc function. The function tries to reallocate memory where the variable mac is stored, on the stack. No wonder it's an invalid pointer.
By passing &mac you are simply taking a step in the wrong direction while dereferencing pointers.

NULL as a parameter

I am a bit confused when you pass NULL as a parameter
for example
int* array_create( int* array,size)
{
array = new int[size];
return array;
}
int main()
{
int* array = array_create(NULL,10);//can we pass NULL in this case?
delete[] array;
return 0;
}
I know the example is kinda stupid, but I am wondering if we can pass NULL as the parameter when the function assigns some heap memory to a pointer and returns it?
When you call your function like this...
int* array = array_create(NULL,10);//can we pass NULL in this case?
...you are getting behaviour like:
int* array_create(...)
{
int* array = NULL;
size_t size = 10; // using size_t as you'd missed any type
array = new int[size];
return array;
}
Ultimately, array is initialised to NULL then shortly afterwards overwritten with the value returned by new, so the initialisation serves no purpose.
For this code, there was simply no point passing an array argument... you could have created a local variable directly:
int* array_create(size_t n)
{
int* array = new int[size];
return array;
}
...or even...
int* array_create(size_t n)
{
return new int[size];
}
I am wondering if we can pass NULL as the parameter when the function assigns some heap memory to a pointer and returns it?
This requirement doesn't make much sense, as the two things are unrelated. You can pass whatever you like, and return whatever you like.
More commonly, a function might do something like:
void dump_bytes(std::ostream& os, unsigned char* p, size_t n)
{
if (p)
for (size_t i = 0; i < n; ++i)
os << static_cast<int>(p[i]) << ' ';
}
In dump_bytes, specifying a p value of NULL would fail the if (p) condition, ensuring the function didn't invoke undefined behaviour by dereferencing via a NULL pointer, even if n was not 0.
Just summarizing from the comments:
Yes, it is completely valid, but in Your example it is completely useless (you know that)
Some examples of this in real code:
In OpenGL you can tell the API if the data you want is coming from is from a buffer:
glBufferData(..., nullptr);
But wait! That's not null, that's nullptr?
Well in a c++11 compiler nullptr is a better option. Because NULL often usually resolves to 0, a version of the method that takes an int instead of a pointer the compiler will choose the int.
Here's some more data on that:
http://en.cppreference.com/w/cpp/language/nullptr
Also, if you want to edit an array, you should pass a pointer to a pointer.

How to avoid dynamic allocation of memory C++

[edit] Outside of this get method (see below), i'd like to have a pointer double * result; and then call the get method, i.e.
// Pull results out
int story = 3;
double * data;
int len;
m_Scene->GetSectionStoryGrid_m(story, data, len);
with that said, I want to a get method that simply sets the result (*&data) by reference, and does not dynamically allocate memory.
The results I am looking for already exist in memory, but they are within C-structs and are not in one continuous block of memory. Fyi, &len is just the length of the array. I want one big array that holds all of the results.
Since the actual results that I am looking for are stored within the native C-struct pointer story_ptr->int_hv[i].ab.center.x;. How would I avoid dynamically allocating memory like I am doing above? I’d like to point the data* to the results, but I just don’t know how to do it. It’s probably something simple I am overlooking… The code is below.
Is this even possible? From what I've read, it is not, but as my username implies, I'm not a software developer. Thanks to all who have replied so far by the way!
Here is a snippet of code:
void GetSectionStoryGrid_m( int story_number, double *&data, int &len )
{
std::stringstream LogMessage;
if (!ValidateStoryNumber(story_number))
{
data = NULL;
len = -1;
}
else
{
// Check to see if we already retrieved this result
if ( m_dStoryNum_To_GridMap_m.find(story_number) == m_dStoryNum_To_GridMap_m.end() )
{
data = new double[GetSectionNumInternalHazardVolumes()*3];
len = GetSectionNumInternalHazardVolumes()*3;
Story * story_ptr = m_StoriesInSection.at(story_number-1);
int counter = 0; // counts the current int hv number we are on
for ( int i = 0; i < GetSectionNumInternalHazardVolumes() && story_ptr->int_hv != NULL; i++ )
{
data[0 + counter] = story_ptr->int_hv[i].ab.center.x;
data[1 + counter] = story_ptr->int_hv[i].ab.center.y;
data[2 + counter] = story_ptr->int_hv[i].ab.center.z;
m_dStoryNum_To_GridMap_m.insert( std::pair<int, double*>(story_number,data));
counter += 3;
}
}
else
{
data = m_dStoryNum_To_GridMap_m.find(story_number)->second;
len = GetSectionNumInternalHazardVolumes()*3;
}
}
}
Consider returning a custom accessor class instead of the "double *&data". Depending on your needs that class would look something like this:
class StoryGrid {
public:
StoryGrid(int story_index):m_storyIndex(story_index) {
m_storyPtr = m_StoriesInSection.at(story_index-1);
}
inline int length() { return GetSectionNumInternalHazardVolumes()*3; }
double &operator[](int index) {
int i = index / 3;
int axis = index % 3;
switch(axis){
case 0: return m_storyPtr->int_hv[i].ab.center.x;
case 1: return m_storyPtr->int_hv[i].ab.center.y;
case 2: return m_storyPtr->int_hv[i].ab.center.z;
}
}
};
Sorry for any syntax problems, but you get the idea. Return a reference to this and record this in your map. If done correctly the map with then manage all of the dynamic allocation required.
So you want the allocated array to go "down" in the call stack. You can only achieve this allocating it in the heap, using dynamic allocation. Or creating a static variable, since static variables' lifecycle are not controlled by the call stack.
void GetSectionStoryGrid_m( int story_number, double *&data, int &len )
{
static g_data[DATA_SIZE];
data = g_data;
// continues ...
If you want to "avoid any allocation", the solution by #Speed8ump is your first choice! But then you will not have your double * result; anymore. You will be turning your "offline" solution (calculates the whole array first, then use the array elsewhere) to an "online" solution (calculates values as they are needed). This is a good refactoring to avoid memory allocation.
This answer to this question relies on the lifetime of the doubles you want pointers to. Consider:
// "pointless" because it takes no input and throws away all its work
void pointless_function()
{
double foo = 3.14159;
int j = 0;
for (int i = 0; i < 10; ++i) {
j += i;
}
}
foo exists and has a value inside pointless_function, but ceases to exist as soon as the function exits. Even if you could get a pointer to it, that pointer would be useless outside of pointless_function. It would be a dangling pointer, and dereferencing it would trigger undefined behavior.
On the other hand, you are correct that if you have data in memory (and you can guarantee it will live long enough for whatever you want to do with it), it can be a great idea to get pointers to that data instead of paying the cost to copy it. However, the main way for data to outlive the function that creates it is to call new, new[], or malloc. You really can't get out of that.
Looking at the code you posted, I don't see how you can avoid new[]-ing up the doubles when you create story. But you can then get pointers to those doubles later without needing to call new or new[] again.
I should mention that pointers to data can be used to modify the original data. Often that can lead to hard-to-track-down bugs. So there are times that it's better to pay the price of copying the data (which you're then free to muck with however you want), or to get a pointer-to-const (in this case const double* or double const*, they are equivalent; a pointer-to-const will give you a compiler error if you try to change the data being pointed to). In fact, that's so often the case that the advice should be inverted: "there are a few times when you don't want to copy or get a pointer-to-const; in those cases you must be very careful."

What is the benefit of using double pointer in C/C++ [duplicate]

This question already has answers here:
Need of Pointer to pointer
(5 answers)
Closed 9 years ago.
I am new to C/ C++.
I was going through some of the coding questions related to trees and came across this double pointer notation. Can we do the same things using single pointer as first argument in the below function as we can do with double pointers.
void operate(struct Node *root, struct Node **head_ref){ //do something}
There are two ways of interpreting a pointer; a reference to something, or an array. Considering this is a tree, this is probably the first: a reference to another pointer.
Every argument to a function in C is passed by value, which means that if you change the pointer inside the function, it won't be changed outside. To guarantee it is also changed outside, you can use a reference to the pointer: double pointers. You can consider the following example.
void function(int a) {
a = 5;
}
Even if a is changed above, it is not changed outside of the function. But in this other case,
void function(int * a) {
*a = 5;
}
the value a is changed outside the function as well. The same thought process can be applied to a pointer(which is also a value).
When you want a function to take care of malloc, free is the main reason.
This is useful if you want to encapsulate memory allocation.
For example some init(struct some_struct **), free(struct some_struct **).
And let functions take care of malloc, free. Instead of allocating on stack.
For example a function that packs a string of unknown length.
size_t pack_struct(char** data, const struct some_struct * some_struct)
{
/**
* #brief buffer
* #note verify the needed buffer length
*/
char buffer [256]; // temporary buffer
*data = 0;
//const char* package_pattern = "%cW ;%u.%u;%s%c";
size_t len = sprintf(buffer, weight_package_pattern,
START_CHARACTER,
some_struct->ts.tv_sec,
some_struct->ts.tv_usec,
some_struct->string_of_unknown_length, // but no more then buffer
STOP_CHARACTER);
if(len == 0) {
perror("sprintf failed!\n");
return len;
}
// len++; // for end character if wanna some, see sprintf description
*data = (char*)malloc(len*sizeof(char)); // memory allocation !
strncpy(*data, buffer, len);
return len;
}
However such technic should be avoided when programming in C++.
Double pointer is normally used when allocating memory.
#include <stdlib.h>
void new_malloc(void **p, size_t s) {
*p = malloc(s);
/* do something */
}
int main() {
int *p;
new_malloc((void **)&p, sizeof(int) * 10);
}

problem with passing custom array to function (c++)

I have an array of type T which I pass as a pointer parameter to a function.
The problem is that I can't write new data to this array properly, without getting memory violation at the second try.
In this code I read integers from a text file and pass them to the function (part of template class of type T), in order to append them to the array.
After I finish to append the integers, I want to use the same array back in the Main.
Does someone know what's wrong with the code?
Thanks, Max
template<class T> int CFile<T>::read(T **apBuf, int aNum)
{
int readCounter = 0;
*apBuf = (T*)malloc(sizeof(T)*aNum);
for (int i = 0; i<aNum; i++)
{
T var = read();
if (var == NULL)
{
if (isEof)
{
return readCounter;
}
else
{
perror ("Error Reading File - Insufficient var type");
return -1;
}
}
else
{
*apBuf[i] = var;
readCounter++;
}
}
return readCounter;
}
*apBuf[i] = var;
This is parsed as if it was written:
*(apBuf[i]) = var;
This is obviously not what you want; apBuf is a pointer to a pointer to an array; you are treating it as a pointer to an array and you are dereferencing the ith element of it. What you really mean is:
(*apBuf)[i] = var;
*apBuf gives you "the object pointed to by apBuf," which is the array; then you obtain the ith element of the array.
That said, this is rather unusual: why not accumulate the data into a std::vector<T> and return that from the function? Then you don't have to worry about the explicit dynamic memory management. (Also, is T always a pointer type? If not, then var == NULL makes no sense.)
Well, you used malloc to allocate the array, and then tried to assign to it. This is undefined behaviour, because you have to construct the objects.
Oh, and you should really, really consider using self-owning resource classes, because malloc and this style of programming in general is hideously unsafe. What if T's copy constructor throws an exception? Memory leak. Just for example.
One issue you have is your using malloc instead of new. If T is a class the constructor won't be called.