I'm still learning c++ and have a question that may be obvious, or maybe I just don't know what I'm trying to do. I have functions that take a matrix (a class I wrote, which has a properly written destructor) and create a new matrix from it, returning a reference to the new one. I need to iterate possibly tens of thousands of times on these matrices so I need to make sure I don't have any memory leaks. So, the question is, how do I properly delete the matrix I don't need any more in order to make space for the next one? Here's the code I'm trying to get leak-free:
DynamicMatrix<double> x0 = getX0(n);
DynamicMatrix<double>exactU = getExactU(n);
DynamicMatrix<double> b = getB(n) * w;
DynamicMatrix<double> x1 = getX1(x0, b, w, n);
while( !isConverged(exactU,x1,e) ){
delete x0; //<<<<< This doesn't work. Nor does delete &x0.
x0 = x1;
x1 = getX1(x0, b, w, n);
}
Each of the getX() methods creates a pointer to a matrix, and returns a reference to the matrix as in getX0():
DynamicMatrix<double> &getX0(int n){
DynamicMatrix<double>* mat1 = new DynamicMatrix<double>(n * n,1);
for (int i = 1 ; i <= n; i++){
for (int j = 1; j <= n; j++){
mat1->set((i-1)*n +j, 1, 0);
}
}
return *mat1;
}
So then, calling 'delete X0' errors because it needs a pointer. 'delete &X0' says the pointer being freed was not allocated. What is the correct way to do this? Or am I doing something completely wrong? With matrices too large and with too many iterations, my large hard drive runs out of space which I can only assume means I have memory leaks galore.
Stroustrup R'lyeh Fhtagn.
Writing MyType myVar = MyFunction() creates a brand new object using a constructor that accepts the return type of myFunction as an argument. Whatever was returned by myFunction is then discarded - in your example, getX0 returns a reference to an object that was allocated dynamically, and is therefore leaked.
Seriously, though - try creating the matrices on the stack (without new) and returning them as-is. Shouldn't cause too much trouble, since they appear to allocate their data dynamically on the inside anyway, and I suspect NRVO would apply to avoid making a copy (the returned matrix would be directly constructed into the appropriate location. The x0 and x1 magic at the bottom can be implemented as follows:
x0.swap(x1);
DynamicMatrix<double> temp = getX1(x0, b, w, n);
x1.swap(temp);
Since a swap operation can be implemented on your dynamic matrix in terms of a pointer swap (which is very fast) instead of an actual data copy, this should be extremely fast.
You should use pointers. The statement
DynamicMatrix<double> x0 = getX0(n);
Makes a copy of a matrix. You want
DynamicMatrix<double> *getX0(int n){
DynamicMatrix<double>* mat1 = new DynamicMatrix<double>(n * n,1);
...
return mat1;
}
Then
DynamicMatrix<double> *x0 = getX0(n);
...
delete x0;
if getX() returns a pointer, you should write as the first line:
DynamicMatrix<double>* x0 = getX0(n);
That would make more sense, as you return a new pointer. Then you have to delete it as you show some lines below.
Note however that you can save a lot of troubles using boost::shared_ptr:
typedef boost::shared_ptr<DynamicMatrix<double> > dyn_matrix_ptr;
dyn_matrix_ptr x0 (getX0(n));
// use x0 as a normal pointer
...
// You don't have to manually delete it, it will be deleted automatically.
Your bug is here:
DynamicMatrix<double> x0 = getX0(n);
You dont necessarily have to use pointers. You can return a reference to the newed object. To delete the memory just take the address of the reference.Taking the address of a reference gives you the address of the referent; you should be able to call
// receive newed memory in a reference
DynamicMatrix<double>& x0 = getX0(n);
// &x0 should give you the address of the allocated memory.
delete &x0;
The rules for DynamicMatrix<double> are fundamentally the same as they are for int.
If it was allocated on the stack as an 'auto' variable, then the correct way to clean it up is to do nothing - just let it fall out of scope. You want to arrange your code, as much as possible, such that this is the case.
If it was allocated with 'new', clean it up with 'delete'.
Please don't ever dynamically allocate something and then return it by reference. Return the pointer. Actually, don't do that, either. Use a smart pointer class. Please.
Please don't dynamically allocate things if you don't need to. Just make a local value, and return it - by value (this is how you deal with the fact that you can't return a reference to a non-static local). You would never, ever, ever think about writing code like the following, right?
int& give_me_a_value() {
int* result = new int(rand());
return *result;
}
Again: the rules for DynamicMatrix<double> are fundamentally the same as they are for int. That's why you implement copy constructors, assignment operators and destructors: so that this actually works the way you'd reasonably expect it to.
Related
Like i said in the title i cant get the destructor to work. The reason being is that in this program i am required to use a int* array with negative indices: I keep getting this error at random times while running also: Microsoft C++ exception: std::bad_alloc at memory location 0x009DF130.
heres the code that i believe involves the error:
private: int* run;
IntArray::IntArray(int a, int b)
{
int c = b-a;
run = new int [c] + a; //This is how i give it a negative indicie
h = b;
l = a;
}
IntArray::~IntArray()
{
delete[]run;
}
string IntArray::setName(string sp)
{
s = sp;
return s;
}
void runSim() {
IntArray b(-4, 6);
for (int i = b.low(); i <= b.high(); i++)
// low is the lowes bound high is the highest
b[i] = i * 10;
b.setName("b"); //this is where it breaks and gives me that error
wait();
}
The only right way to do this is to define a custom operator[] on your class. The code you have has numerous errors:
You access both low and high, that's high-low+1 elements. But you only allocate high-low.
If p=new int[high-low+1], then run=p+low; and run[low] means *(p + low + low). This is the proximate cause of your crash -- you wrote way outside the array, trashing internal metadata, which made dynamic allocation fail for the next user, your string's assignment operator.
You should have subtracted low when computing run, so that run[low] would give p[0], the first allocated element. But this might calculate a pointer outside the array (when low is positive), which is undefined behavior.
You pass a pointer to delete[] that didn't come from array new. You need to pass p, not run, to delete[].
You have no attempt at exception safety. Management of dynamic memory in C++ is an advanced topic, and the evidence shows that you are not ready to do it yet. So use an existing smart pointer to manage your memory.
Here's a better version:
#include <memory>
template<typename T>
class ArbBoundArray
{
int low;
std::unique_ptr<T[]> base;
public:
ArbBoundArray(int l, int h) : low(l), base(new T[h-l+1]) {}
T& operator[](int o) { return base[o-low]; }
const T& operator[](int o) const { return base[o-low]; }
};
That's it. Less code, works for any type not just int, and exception-safe.
You can add your special needs like a name or whatever on top of that basic concept.
Your have a simple errors:
Do not pass a value to delete [] you didn't get from new [] (or already passed once).
You need to undo your pointer-arithmetic to get the right pointer.
Also, be aware that if you create a pointer which points outside the array using pointer-arithmetic, you have Undefined Behavior.
If that's not your actual code, beware of trying to allocate less than 1 element.
Since you add a (aka l) to run when you new it, you must subtract when you delete it:
delete[] (run - l);
Not trying to be mean, but this is pretty bad code.
First of all, if b - a returns a number less than 0 you will probably get an std::bad_alloc and if a > c you will be stepping into undefined behaviour [scary] territory and will probably get a segfault if you try to use the pointer.
Seeing as though you try to delete[] the pointer that points to new int[c] + a you almost certainly will get a segfault.
You need to do run -= a before trying to delete[] it, the implementation will either store information about any new or malloc in the space before the pointer that you get given so that when you delete or free the memory it just has to run behind the pointer and get any information it needs or store the info in a hidden array somewhere that is indexed by the numerical representation of the pointer. But probably the first. Either way, you're screwed doing what you're doing.
in Visual Studio 2010 i create a while statement in which i assign a pointer to pointer to a map.
Example:
std::map<int,std::tuple<int,std::string>** > dmap;
int i=0;
while (i<3){
std::tuple<int,std::string>* t = new std::tuple<int,std::string>(10+i,std::string("test"));
dmap[i] = &t;
dmap[i + 1 ] = &t;
i++;
}
.
.
.
for (auto it = d.begin();it!=d.end();++it)
{
if(*(it->second) != nullptr){
delete *(it->second);
*(it->second) = nullptr;
}
}
The problem is that the address of &t is always the same and so at the end the map always contains , for all keys that i entered, the last *t value.
What's the problem? (Resolved)
[Edit]
Now i modify the code beacause before it was incomplete, if i want to avoid to delete nullptr i need to have a pointer to pointer. Or not?
The problem is that you're putting a pointer to a local variable t into the map. After each loop, t is destroyed and the pointer is no longer valid.
I've no idea why you're using pointers at all, let alone pointers to pointers. You probably want to put the tuples themselves in the map:
std::map<int,std::tuple<int,std::string>> dmap;
for (int i = 0; i<3; ++i){
dmap[i] = {10+i, "test"};
}
i create a while statement in which i assign a pointer to pointer to a map
Sorry for saying this, but it sounds to me like you have bigger problems than the fact that t is the same (this looks like the xy problem).
Consider (in order) one of these alternatives:
store your tuples by value
store your tuples by single pointer (worse than "by value", better than "by pointer to pointer"). If you can do this, consider declaring your map over std::shared_ptr<std::tuple<...>>)
if you really need a map of pointers to pointers to tuples, consider creating a minimal proxy object that acts like a smart pointer to pointer internally (and manages the allocations for you in a safe manner) and like a regular type from the outside (and redeclare your map accordingly).
Either way, if you really need a map of pointers to pointers to tuples (for some reason), the allocation should be done like this:
std::map<int,std::tuple<int,std::string>**> dmap;
int i=0;
while (i<3) {
*dmap[ i ] = new std::tuple<int,std::string>{10 + i, "test"};
++i;
}
(The way you did it added the address of the same local (stack) variable to the map, which would lead to undefined behavior after you exit the local function).
Why are you interested in std::tuple<int,std::string>** ?
Wouldn't a std::tuple<int,std::string>* be sufficient ?
std::map<int,std::tuple<int,std::string>* > dmap;
int i=0;
while (i<3){
std::tuple<int,std::string>* t = new std::tuple<int,std::string>(10+i,std::string("test"));
dmap[i] = t;
i++;
}
Well, the address of t is always the same, because it is local variable that is stored on your stack. Each time you enter the block, t will be allocated on the same spot (as you're destroying t after you get out of your while body).
Instead, you need to allocate it on the heap (if this is really what you want to do).
std::tuple<int,std::string>** t = new std::tuple<int,std::string>*();
*t = new std::tuple<int,std::string>(10+i,std::string("test"));
dmap[i] = t;
I can't see what you're trying to accomplish, but this would be a better solution:
std::map<int,std::tuple<int,std::string>* > dmap;
int i=0;
while (i<3){
std::tuple<int,std::string>* t = new std::tuple<int,std::string>(10+i,std::string("test"));
dmap[i] = t;
i++;
}
Even better would be to use smart pointer instead raw one.
Even better would be to store objects by value (no pointers at all).
please can you help me with my problem with complex arrays in C++? If I have an array Arr[N] of cmplx numbers and now I need the real part of the Arr[i]. In header there is an complex array CompArray defined as
cmplx** CompArray;
and then I allocate it to have dimension [nmax][nmax]
then I have a function1 where I use only part of this and write
myclass::function1(double* realArray)
realArray = new double [nmax];
cmplx* ComplexArray [nmax];
ComplexArray[] = CompArray[10][];
for(int i=0;nmax;i++){
realArray[i] = ComplexArray[i].real();
}
I get an error:
error: expression must have class type
the error is the same for real() or imag() functions
cmplx* ComplexArray [nmax];
That's not an array of complex numbers; it's an array of pointers to numbers. It looks like you need a pointer to (the first of) an array of numbers:
cmplx* ComplexArray = CompArray[10];
Then ComplexArray[i] is a complex number (an expression with "class type") as required.
Once you've fixed that, this looks a bit dodgy:
realArray = new double [nmax];
You've been passed a pointer, then you throw it away and allocate a new array. The caller won't see that array, so all you've done is leak memory. You could pass the pointer by reference, or return it from the function; that way the caller will at least get the results.
However, it's a bad idea to pass around raw pointers to dynamic memory and hope they get deleted at the right time. Instead, pass around objects which are responsible for managing the memory; in this case, a container would be ideal:
std::vector<double> myclass::function1() {
std::vector<double> realArray;
cmplx* ComplexArray = CompArray[10];
for(int i=0;i<nmax;i++){
realArray.push_back(ComplexArray[i].real();
}
return realArray;
}
I would like to be sure that this is not wrong: I initialize array with
double* lower = input->getLowerBox();
where function getLowerBox() returns some double*. is it correct? Or shold I initialize this way::
double* lower = new double[nbP];
for (int i=0;i<nbP;i++)
lower[i]=input->getLowerBox()[i];
or to avoid multiple calls to getLowerBox,
double* lower = new double[nbP];
double* tmp = input->getLowerBox();
for (int i=0;i<nbP;i++)
lower[i]=tmp[i];
delete[] tmp;
Two steps recipe:
Change Input::getLowerBox() to return std::vector<double> const&
Use a copy if you want to modify the returned value, and the const reference instead
Well, it depends on what you want to do. Do you need a new array or not.
Your first snippet doesn't create a new array, so memory management is more important.
For example:
double* lower = input->getLowerBox();
delete[] lower;
would possibly render input->getLowerBox() invalid. Or something like:
double* lower = NULL;
{
Class input;
lower = input->getLowerBox();
}
//...
would make lower a dangling pointer, if input clears the contents of the array in the destructor.
The last two snippets create new arrays. It is safer IMO, but also uses extra memory.
Both are correct, depending on what you want to do. Whichever you choose, make sure to document it fully.
The first way is fine. You're going to return a pointer to a double, which I'm assuming is related to an array (If not, then please correct me). By doing that, you're pointing to the first element of that array and then you can just index lower or use pointer arithmetic to access the other elements.
EDIT: Could you post the definition of getLowerBox() so it's more clear to what you're trying to do?
Do you have the ability to change getLowerBox() ? If so, I would change it so it returns a vector.
Depending on the implementation, it might return you a pointer which you can own or a pointer to an internal static (bad but possible) so you need to know what it's doing and act accordingly by retaining the pointer or taking a copy of the array respectively.
If you don't have control over getLowerBox() and you know the size of the array it returns, it would be a reasonable idea copy it to a vector
double* lower = input->getLowerBox();
vector<double> lowerV(lower, lower + N );
(where N is the size of the array - BTW this is just from memory, I haven't compiled it.)
I would definitely go with the first one for multiple reasons. It's cleaner, it avoids unnecessary calls / variable creation, etc. Just make sure that input's a pointer if you're using "->"; otherwise use ".".
Right now I have a pointer set to a row in my 2D array. I want that pointer to stop pointing to that row, but I will be using the pointer later for something else. I just want to know how to unset the pointer after it is initialized and has pointed to a row.
double* tempRow;
tempRow = (double*) malloc(size * sizeof(double));
...
tempRow = NULL;
doesn't unlink the tempRow variable from the array row. Why not?
I wonder if I should be using C then instead. Will there be overhead when using a vector?
While you have written will set tempRow to NULL, it wont release the memory you have allocated. For that you need
free(tempRow);
tempRow = NULL;
However if you're using C++ as the tags suggest, you'd be better off using C++ new/delete
double* tempRow;
tempRow = new double[size];
...
delete [] tempRow;
tempRow = NULL;
you can even use the STL to handle your memory allocation for you.
std::vector<double> tempRow(size);
// You can access the data, in a similar way to an array
tempRow[5] = tempRow[4]+tempRow[3];
// If you really need to access the underlying pointer, (To pass to another
// function for example) you can do this. Note that the pointer will be valid
// until the vector is destroyed or modified in certain ways that can cause the
// vector to reallocate its memory. So you can't use this to pass data to a
// function that destroys or takes ownership of the passed in pointer.
fn_requiring_pointer( &temp[0] );
// The memory used in tempRow will get cleaned up automatically when the
// object goes out of scope
//
// If I really need to free up the memory used in it early I can use a swap
// hack. (iirc tempRow.clear() isn't guaranteed to release the memory)
std::vector<double>().swap(tempRow); // Unneeded in most cases.
Also trying to reuse the tempRow pointer for something unrelated is probably not necessary. Just create a new pointer with a different name. Reusing a variable form multiple different unrelated purposes can make code very hard to understand later.
I'm new at C++ as well, but a while ago, someone told me that using std::vector is a much safer approach to handling arrays of data.
Automatic re-allocation when adding more elements.
Iterators for use with stuff from #include <algorithm>.
Bounds-protection with .at(index) element access.
No messy pointer-tracking required.
C-array style access with operator[].
RAII.
You would declare a vector like this:
std::vector<double> tempRow(size);
tempRow[0] = 3.00;
tempRow[1] = 1.00;
// no need to use delete[] or free(), it will destruct itself
// and relinquish its resources automatically.
The example you've shown should work.Also if you've not freed the memory before making temRow NULL, you are leaking memory.
double* tempRow;
tempRow = (double*) malloc(size * sizeof(double));
...
free(tempRow); // free the memory.
tempRow = NULL; // reset the pointer.
...
tempRow = &some_other_double_var; // reuse the pointer.
Doesn't seem to work?
That's the worst complaint and a solution providers's nightmare.
Do you mean you get a compilation error?
If yes, did you include <cstdio>? and using namespace std;
Doesn't work in what way? The normal way to "unset" a pointer in C++ is with:
tempRow = 0;
but what you have should be fine, assuming you've included the correct headers or otherwise have the correct definition for NULL.
As an aside, you should first call free() on that memory before losing the pointer, otherwise you'l have a memory leak (and this is assuming you have a good reason to use C-style malloc/free instead of the more kosher C++ new/delete).