Problem allocating memory

elito
elito used Ask the Experts™
on
I have the following extremely simple code:

void AllocateMemory(float* M, int n)
{
     M = new float[n];
}
int main(int argc, char* argv[])
{

     float* k = NULL;
     AllocateMemory(k);

     if (k) //k is still NULL ????
          delete [] k;
     return 0;
}



In the main function, I have declared a pointer and I want to allocate memory for this pointer in another function (AllocateMemory). However, after calling function AllocateMemory, the value of k is NULL.
What am I missing here?

Thanks,
elito
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®

Commented:
You are the victim of the joys and perils of call by value. In C and C++ arguments are passed to functions by copying them onto the stack. Therefore, what the function gets is not, in fact, the variable itself but a copy of it. The advantage of this is that the caller does not have to worry about functions "corrupting" its variables. Such side effects are in fact common (in languages where it is possible) and cause a lot of grief. The chief reason is that when inspecting a piece of code, the function call doesn't *appear" to do anything to the variable. You would only be able to tell that, if you looked up the function, which is usually somewhere else.

The *disadvantage*, as you have just discovered, is the flip side of the same coin. A function cannot change the value of an argument, even when that is what you really intended.

There are a number of solutions for your particular situation. The one I would recommend is to return the value you are after. Something like:

float * AllocateMemory(int n)
{
    return(new float[n]);
}
int main(int argc, char* argv[])
{

    float* k = NULL;
    k=AllocateMemory();

    if (k) //k is still NULL ????
         delete [] k;
    return 0;
}



This is the standard way of getting values out of functions. C++ also offers pass by reference. And finally, there is the old C standby, passing in a pointer to the pointer.

Commented:
First, your code couldn't possibly compile since

AllocateMemory takes two arguments and you used it in your main passing only one argument.

Secondly, you should pass the pointer to the pointer of float. Otherwise what you are passing is a copy of your float pointer.

Here would be the correct code:


void AllocateMemory(float** M, int n) // << corrected from float *M to float** M
{
    *M = new float[n];
}
int main(int argc, char* argv[])
{

    float* k = NULL;
    AllocateMemory(&k, 100);  // corrected  selected 100 as n

    if (k) //k is still NULL ????
         delete [] k;
    return 0;
}

Author

Commented:
OK, but what if I want to allocate two or more arrays in the same function?
e.g.

void AllocateMemory(float* M, float* N, int np)
{
   (...)
}

Learn Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

Author

Commented:
kimpan,

Yep, that was the problem. I feel stupid now :-(

Thanks

Commented:
I would suggest you to use STLs vector instead of arrays then you wouldn't have to worry about allocating with new or worry about when to call delete (or find out in run-time that you forgot to delete or deleted several times which probably would case program crash)

You can use vector virtually wherever you use arrays. Even those system calls requiring arrays as passing arguments.

I will give you an example assuming you are not familiar with STL vector. I apologize if I am assuming that incorrectly.

***************

#include <vector>

int main()
{
   vector<float> M;

   M[0] = 1.0;
   ...
   M[56] = 1.2;

   // done, no need to write new or delete yourself  
}

***********

The M will grow dynamically as you put values into it and if you know from beginning the size you want for your vector, it is optimal to reserve that amount of memory before you use it:

...

  vector<float> M;

  M.reserve(1000);

...

*************

and to pass vector where a function requires an array:

void funcTakingArray(float *aFloat, int size)
{
  ...
}

...

vector<float> M;

...

funTakingArray(&M[0], M.size());

***************


You can also pass from array to vector easily. I will show you that and more at request



Author

Commented:
Thanks a lot Kimpan! I would really appreciate if you could give me more information about the use of stl vectors, e.g. how to pass from array to vector.
Also, what about performance issues? Is it possible that stl vectors introduces a significant overhead respect standard arrays for example in high-performance real time applications?

cheers,
elito

Author

Commented:
And what's the difference between using vector::resize() and vector::reserve? Which is better to use when you know beforehand the dimensions of the vector?

Commented:
reserve would be to prefer if you don't have any elements in your vector or if you don't care to keep elements inside your vector. resize is to use when you wanna keep the elements you have in your vector. If you make your vector bigger with resize, it will append elements that means if you have a vector:

std::vector<MyClass> vec;

vec[0] = ..
vec[10] = ..

and you call

vec.resize(100),  it will append 90 objects of MyClass to your vector. That means MyClass default constructor will be called 90 times.

if you use reserve, the vec will simply allocate/reallocate memory to hold the elements.


Author

Commented:
Thanks!

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial