473,386 Members | 1,830 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

memory leak in class code

hello all!

i'm using gcc 3.2 on linux.
i have a (self developed) matrix class:

class cMatrix { // unneccessary info stripped
....
double *data; // matrix data is stored in a heap array

cMatrix row(const int& r) const;
// const cMatrix& row(const int& r) const; // is this better?? why?
....
const double& dotproduct(const cMatrix& m1, const cMatrix& m2) const;
....
}

cMatrix cMatrix::row(const int& r) const {
cMatrix *tmp=new cMatrix(1,ncols);
for(int i=0;i<ncols;i++) (*tmp)[i]=data[r*ncols + i];
return *tmp;
}

const double& cMatrix::dotproduct(const cMatrix& v1, const cMatrix& v2)
const {
double d=0.0;
for(int i=0;i<v1.elements();i++) d+=v1[i]*v2[i];
return d;
}
int main() {

{
cMatrix m(10,10);
cMatrix r=m.row(1);
}

return 0;
}

using valgrind i found out that the above main() leaks memory.

my questions are:
* how to alter the code of cMatrix::row to avoid memory leaks?
* how to avoid objects stored on the stack that get overriden later
when program code is further executed?
* is there a better syntax for (*tmp)[i]="some value"?

additional info:
* i later definitly need something like
res=dotproduct(Ni, nodes.column(i)); (where Ni is also a matrix)
to work correctly.(^^^^^^^^^^^^^^^ temporary object)
-> operator and method chaining.

thanks for any help or ideas!

--
flo
Jul 19 '05 #1
10 2805
"florian kno" <fl****@yahooQ.com> wrote in message
news:lV**********************@news.chello.at...
hello all!

i'm using gcc 3.2 on linux.
i have a (self developed) matrix class:

class cMatrix { // unneccessary info stripped
...
double *data; // matrix data is stored in a heap array

cMatrix row(const int& r) const;
// const cMatrix& row(const int& r) const; // is this better?? why? ...
const double& dotproduct(const cMatrix& m1, const cMatrix& m2) const; ...
}

cMatrix cMatrix::row(const int& r) const {
cMatrix *tmp=new cMatrix(1,ncols);
for(int i=0;i<ncols;i++) (*tmp)[i]=data[r*ncols + i];
return *tmp;
}

const double& cMatrix::dotproduct(const cMatrix& v1, const cMatrix& v2) const {
double d=0.0;
for(int i=0;i<v1.elements();i++) d+=v1[i]*v2[i];
return d;
}
int main() {

{
cMatrix m(10,10);
cMatrix r=m.row(1);
}

return 0;
}

using valgrind i found out that the above main() leaks memory.

my questions are:
* how to alter the code of cMatrix::row to avoid memory leaks?
Don't use 'new' when you don't have to:

cMatrix cMatrix::row(const int& r) const
{
cMatrix tmp(1,ncols);
for(int i=0;i<ncols;i++)
{
tmp[i] = data[r*ncols + i];
}
return tmp;
}

In C++ you don't have to use 'new' to instatiate class objects.
* how to avoid objects stored on the stack that get overriden later
when program code is further executed?
I don't understand this question???
* is there a better syntax for (*tmp)[i]="some value"?
If you don't use pointers like in the (untested) code I showed you, you
don't get the ugly syntax.
additional info:
* i later definitly need something like
res=dotproduct(Ni, nodes.column(i)); (where Ni is also a matrix)
to work correctly.(^^^^^^^^^^^^^^^ temporary object)
-> operator and method chaining.


I don't see your problem here.

--
Peter van Merkerk
peter.van.merkerk(at)dse.nl

Jul 19 '05 #2
hello!

Peter van Merkerk wrote:
"florian kno" <fl****@yahooQ.com> wrote in message
news:lV**********************@news.chello.at...
my questions are:
* how to alter the code of cMatrix::row to avoid memory leaks?


Don't use 'new' when you don't have to:

cMatrix cMatrix::row(const int& r) const
{
cMatrix tmp(1,ncols);
for(int i=0;i<ncols;i++)
{
tmp[i] = data[r*ncols + i];
}
return tmp;
}

In C++ you don't have to use 'new' to instatiate class objects.


ok.
* how to avoid objects stored on the stack that get overriden later
when program code is further executed?


I don't understand this question???


i was thinking that the local objects are stored on the stack (that's why i
created new ones not on the stack) and that a reference is returned to
memory space that is later overwritten.
additional info:
* i later definitly need something like
res=dotproduct(Ni, nodes.column(i)); (where Ni is also a matrix)
to work correctly.(^^^^^^^^^^^^^^^ temporary object)
-> operator and method chaining.


I don't see your problem here.


that's somewhat redundant with my stack problem.

thanks.

--
flo
Jul 19 '05 #3
> > Don't use 'new' when you don't have to:

cMatrix cMatrix::row(const int& r) const
{
cMatrix tmp(1,ncols);
for(int i=0;i<ncols;i++)
{
tmp[i] = data[r*ncols + i];
}
return tmp;
}

In C++ you don't have to use 'new' to instatiate class objects. ok.
* how to avoid objects stored on the stack that get overriden later
when program code is further executed?


I don't understand this question???


i was thinking that the local objects are stored on the stack (that's

why i created new ones not on the stack) and that a reference is returned to
memory space that is later overwritten.


It appears to me that you have a Java mindset. If that is the case keep
telling youself C++ is not Java, even though the syntax looks similar.
Java has reference semantics, C++ has value semantics. This means that
when the function cMatrix::row() returns the tmp object will be copied
into the object that receives the return value (you did implement a copy
constructor, did you?). After the tmp object has been copied, it will be
destroyed. A smart optimizer may be able to optimize the copying away,
but that should be of no concern to you.

Your concern would be valid if cMatrix::row() would return references
(cMatrix&) to local objects. An alternative for your orignal
implementation of the cMatrix::row() function would to let it return a
pointer (cMatrix*), and put the burden of deleting the object on the
caller. It avoids copying of the matrix but generally you want to avoid
this kind of construct, as it is inconvenient for the caller and it may
easilly lead to memory leaks.

--
Peter van Merkerk
peter.van.merkerk(at)dse.nl
Jul 19 '05 #4
Peter van Merkerk wrote:

It appears to me that you have a Java mindset. If that is the case keep
yes, i have a java background. using your hints i have been able to reduce
my memory leaks from 80 to 3. and these 3 will be killed shortly.

the result of my program is still the same so things work.
telling youself C++ is not Java, even though the syntax looks similar.
Java has reference semantics, C++ has value semantics. This means that
when the function cMatrix::row() returns the tmp object will be copied
into the object that receives the return value (you did implement a copy
constructor, did you?).
yes, i have.
After the tmp object has been copied, it will be
destroyed. A smart optimizer may be able to optimize the copying away,
but that should be of no concern to you.

Your concern would be valid if cMatrix::row() would return references
(cMatrix&) to local objects. An alternative for your orignal
implementation of the cMatrix::row() function would to let it return a
pointer (cMatrix*), and put the burden of deleting the object on the
caller. It avoids copying of the matrix but generally you want to avoid
this kind of construct, as it is inconvenient for the caller and it may
easilly lead to memory leaks.


later, when my program continues to grow, i want to do (actually i have to):

result=(matrix1.row(4).crossproduct(matrix2.column (2)).transpose()+matrixtemp
).dotproduct(matrix3.inverse()); // something written here

:))

thanks for your help!

--
flo
Jul 19 '05 #5
Did you implement a destructor?
And did you do a assignment operator and a copy constructor???
If you pass this cMatrix around, i believe you need it ;)

"florian kno" <fl****@yahooQ.com> wrote in message
news:lV**********************@news.chello.at...
hello all!

i'm using gcc 3.2 on linux.
i have a (self developed) matrix class:

class cMatrix { // unneccessary info stripped
...
double *data; // matrix data is stored in a heap array

cMatrix row(const int& r) const;
// const cMatrix& row(const int& r) const; // is this better?? why?
...
const double& dotproduct(const cMatrix& m1, const cMatrix& m2) const; ...
}

cMatrix cMatrix::row(const int& r) const {
cMatrix *tmp=new cMatrix(1,ncols);
for(int i=0;i<ncols;i++) (*tmp)[i]=data[r*ncols + i];
return *tmp;
}

const double& cMatrix::dotproduct(const cMatrix& v1, const cMatrix& v2)
const {
double d=0.0;
for(int i=0;i<v1.elements();i++) d+=v1[i]*v2[i];
return d;
}
int main() {

{
cMatrix m(10,10);
cMatrix r=m.row(1);
}

return 0;
}

using valgrind i found out that the above main() leaks memory.

my questions are:
* how to alter the code of cMatrix::row to avoid memory leaks?
* how to avoid objects stored on the stack that get overriden later
when program code is further executed?
* is there a better syntax for (*tmp)[i]="some value"?

additional info:
* i later definitly need something like
res=dotproduct(Ni, nodes.column(i)); (where Ni is also a matrix)
to work correctly.(^^^^^^^^^^^^^^^ temporary object)
-> operator and method chaining.

thanks for any help or ideas!

--
flo

Jul 19 '05 #6
Jesper Madsen wrote:
Did you implement a destructor?
And did you do a assignment operator and a copy constructor???
If you pass this cMatrix around, i believe you need it ;)

actually i have all of the above mentioned methods.
problem was solved by skipping the pointer stuff (*).
"florian kno" <fl****@yahooQ.com> wrote in message
news:lV**********************@news.chello.at...
cMatrix cMatrix::row(const int& r) const {
cMatrix *tmp=new cMatrix(1,ncols);
for(int i=0;i<ncols;i++) (*tmp)[i]=data[r*ncols + i];
return *tmp;
}


is now:

const cMatrix cMatrix::row(const int& r) const {
cMatrix tmp(1,ncols);
for(int i=0;i<ncols;i++) tmp[i]=data[r*ncols + i];
return tmp;
}

--
flo

Jul 19 '05 #7
> > "florian kno" <fl****@yahooQ.com> wrote in message
news:lV**********************@news.chello.at...
cMatrix cMatrix::row(const int& r) const {
cMatrix *tmp=new cMatrix(1,ncols);
for(int i=0;i<ncols;i++) (*tmp)[i]=data[r*ncols + i];
return *tmp;
}


is now:

const cMatrix cMatrix::row(const int& r) const {
cMatrix tmp(1,ncols);
for(int i=0;i<ncols;i++) tmp[i]=data[r*ncols + i];
return tmp;
}


If you return by value like in this case, there is no point in putting const
before cMatrix. It doesn't do any harm, but it doesn't do any good either.
Since the caller gets a copy of the matrix generated by cMatrix::row(), it
doesn't matter what the caller does with the copy as it won't affect the
object that produced the copy.

If you would return by reference (not a viable option in this example), or
pass values by reference you should use const whenever possible. For
primitive types like 'int' there is usually no benefit in passing them by
const reference because copying is extremely fast for these types. Passing
them by value is often just as fast (if not faster), and results in clearer
code. For objects whose copy constructor may take some time (your cMatrix
class is an example of this) it is advisable to pass them by const
references.

--
Peter van Merkerk
peter.van.merkerk(at)dse.nl

Jul 19 '05 #8
> > Did you implement a destructor?
And did you do a assignment operator and a copy constructor???
If you pass this cMatrix around, i believe you need it ;)


actually i have all of the above mentioned methods.
problem was solved by skipping the pointer stuff (*).
cMatrix cMatrix::row(const int& r) const {
cMatrix *tmp=new cMatrix(1,ncols);
for(int i=0;i<ncols;i++) (*tmp)[i]=data[r*ncols + i];
return *tmp;
}


is now:

const cMatrix cMatrix::row(const int& r) const {
cMatrix tmp(1,ncols);
for(int i=0;i<ncols;i++) tmp[i]=data[r*ncols + i];
return tmp;
}


This solves the memory leak, however you might not want to do this if
your matrix is big since it creates a temporary object, and copies the
data twice. You may not want to do for perfance and resource issues,
if your matrix is large. Oh I just re-read the original code, and
since it was returning *tmp, it has the same issue.

I have no idea how big your matrices are going to be, but if they're
going to be large, you may want to think about another solution.
Since your row function returns a const cMatrix, you could (maybe
somehow) return a pointer into "data", and thus not have to copy it,
which you're doing twice in your current code.

const cMatrix cMatrix::row(const int& r) const {
cMatrix tmp(1,ncols);
for(int i=0;i<ncols;i++){
//COPYING THE DATA HERE...
tmp[i]=data[r*ncols + i];
}
return tmp;
}

and when this is used...

const cMatrix m = (someobject).row(x); // copying the temp object
here, ie copying the data a second time

Maybe it's not an issue, but maybe it is too.

-Brian
Jul 19 '05 #9
> > is now:

const cMatrix cMatrix::row(const int& r) const {
cMatrix tmp(1,ncols);
for(int i=0;i<ncols;i++) tmp[i]=data[r*ncols + i];
return tmp;
}
This solves the memory leak, however you might not want to do this if
your matrix is big since it creates a temporary object, and copies the
data twice. You may not want to do for perfance and resource issues,
if your matrix is large. Oh I just re-read the original code, and
since it was returning *tmp, it has the same issue.


The best approach is to make right first, and make it fast later.
I have no idea how big your matrices are going to be, but if they're
going to be large, you may want to think about another solution.
Since your row function returns a const cMatrix, you could (maybe
somehow) return a pointer into "data", and thus not have to copy it,
which you're doing twice in your current code.
A good optimizer (one that supports return value optimization) might be able
to optimize the redundant copying away. If that is the case returning
pointers would be no faster. The problem with returning pointers is that it
is very inconvient for the caller. For example try transforming this to a
version with pointers that doesn't leak:
result=(matrix1.row(4).crossproduct(matrix2.column (2)).transpose()+matrixtem
p).dotproduct(matrix3.inverse());

Yes, it is possible to do that. But it also terribly inconvenient; it is
extremely easy for the caller to leak memory, it would take many more lines
than the one without pointers and the resulting code would be a lot less
readable.
const cMatrix cMatrix::row(const int& r) const {
cMatrix tmp(1,ncols);
for(int i=0;i<ncols;i++){
file://COPYING THE DATA HERE...
tmp[i]=data[r*ncols + i];
}
return tmp;
}

and when this is used...

const cMatrix m = (someobject).row(x); // copying the temp object
here, ie copying the data a second time

Maybe it's not an issue, but maybe it is too.


If it is an issue (and it may very well be so when dealing with large
matrixes and less than perfect optimizers), an alternative could be to use a
proxy object. This technique has been used often used with string
implementations. The advantage of this technique is that it transparent for
the caller and that it puts the burden on the implementor(s) of the cMatrix
class rather than its users. But this technique has downsides too and it is
easy to get it wrong leading to very obscure bugs.

But like I said before first get it right. If it is too slow, use a profiler
to pinpoint the performance bottlenecks. If it is the copy constructor then
you may consider the techniques discussed here. OTOH the performance
bottleneck might be just as well somewhere else (matrix computations tend to
burn plenty of CPU cycles as well). Anyway I assume this is just an
excersise for the OP. There are plenty of C++ Matrix libraries around, so if
it is a real project it would be more logical to look at those first.

--
Peter van Merkerk
peter.van.merkerk(at)dse.nl


Jul 19 '05 #10
first, thanks for all help here.

Peter van Merkerk wrote:
The best approach is to make right first, and make it fast later.
that's what i do.
I have no idea how big your matrices are going to be, but if they're
going to be large, you may want to think about another solution.
Since your row function returns a const cMatrix, you could (maybe
somehow) return a pointer into "data", and thus not have to copy it,
which you're doing twice in your current code.


a pointer into data would be possible only in the case of row. if i use
column, what i also have to, things will be more complicated. i would have
to generate a new matrix... (at least in the first point)
A good optimizer (one that supports return value optimization) might be
able to optimize the redundant copying away. If that is the case returning
pointers would be no faster.
when my program is finished i will dive into optimization and look at the
assembly code of my weakest parts a bit and try to make things better
there.

using -O2 instead of -O0 (gcc optimisation level 2) devided the runtime into
half so i think i could do a lot... but first my prog should work
completly.
The problem with returning pointers is that
it is very inconvient for the caller. For example try transforming this to
a version with pointers that doesn't leak: result=(matrix1.row(4).crossproduct(matrix2.colum n(2)).transpose()+matrixtem
p).dotproduct(matrix3.inverse()); Yes, it is possible to do that. But it also terribly inconvenient; it is
extremely easy for the caller to leak memory, it would take many more
lines than the one without pointers and the resulting code would be a lot
less readable.
readablity is a bit issue here since other people will relay on my results
and will propably reuse code.
But like I said before first get it right. If it is too slow, use a
profiler to pinpoint the performance bottlenecks. If it is the copy
constructor then you may consider the techniques discussed here. OTOH the
performance bottleneck might be just as well somewhere else (matrix
computations tend to burn plenty of CPU cycles as well).
the performance bottleneck is indeed somewhere else. its the computation of
the values that get filled in the *big* matrix. and eventually the
inversion of that big matrix.

the row stuff is only for extracting 3 coordinate values of an array of
points.
Anyway I assume
this is just an excersise for the OP. There are plenty of C++ Matrix
libraries around, so if it is a real project it would be more logical to
look at those first.


hmm, no, it is my diploma work for university (sort of phd?). and i'm no
computer programmer. at least i'm not experienced.
one goal of my program is to only use c/c++ and stl.
acutally i look up code from mtl (=matrix template libary) and books
(fortran-code, where my problem is partly described somehow).

--
flo
Jul 19 '05 #11

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Jeremy Lemaire | last post by:
Hello, I am working on cross platform code that is displaying a huge memory leak when compiled on 11.00 HPUX using the aCC -AA flag. It is not leaking on NT, LINUX, Solaris, or HPUX without the...
3
by: Brad Moore | last post by:
Hey All, I need help with debugging some code, if this isn't the correct newsgroup to ask in, disregard this message. I'm having difficulty pinpointing a memory leak in my code, I believe it...
32
by: John | last post by:
Hi all: When I run my code, I find that the memory that the code uses keeps increasing. I have a PC with 2G RAM running Debian linux. The code consumes 1.5G memory by the time it finishes...
10
by: Jonathan Ames | last post by:
Moving to C++ from Java, I'm still confused by some aspects of memory cleanup operations. For example, let's say I have a class MovingObject which maintains a pointer to another class...
6
by: Scott Niu | last post by:
Hi, I have this following simple c++ program, it will produce memory leak ( see what I did below ). My observation also showed that: There will be a mem leak when all the 3 conditions are true:...
4
by: Morten Aune Lyrstad | last post by:
Ok, now I'm officially confused. I have a large project going, which uses a win32 ui library I am developing myself. And I'm getting weird memory leaks. I don't know if I can explain what is going...
20
by: jeevankodali | last post by:
Hi I have an .Net application which processes thousands of Xml nodes each day and for each node I am using around 30-40 Regex matches to see if they satisfy some conditions are not. These Regex...
23
by: James | last post by:
The following code will create memory leaks!!! using System; using System.Diagnostics; using System.Data; using System.Data.SqlClient; namespace MemoryLeak
1
by: =?Utf-8?B?QU1lcmNlcg==?= | last post by:
I may have painted myself into a corner with GenerateInMemory=true. My app need a custom user step. Users want to code (sort of - they are not programmers) some refinements to a search...
3
by: not_a_commie | last post by:
The CLR won't garbage collect until it needs to. You should see the memory usage climb for some time before stabilizing. Can you change your declaration to use the 'out' keyword rather than a 'ref'...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.