I'm currently writing a container in C++, but I encounter problem with memory leak in it.
For test purpose I created 2 versions of main:
First one created and delete object from list in one loop(everything OK here)
Second one create object in first loop and delete all of them in second one(after end of both loops it's still a lot of memory used by program).
OS: Windows Seven;
IDE: CodeBlock 12.11;
Compiler: GNU GCC
Code
(placed in one code block, sorry if it's unclear for someone, just want to make this post as short as possible)
main.cpp:
#include <iostream>
using namespace std;
#include "planetarySystemContainer.hpp"
int main()
{
PlanetarySystemContainer * container;
container=new PlanetarySystemContainer();
PlanetarySystem *planet;
int i;
cin>>i;
i=0;
for(int i=0; i<10000000; i++)
{
planet=new PlanetarySystem();
planet->name("blabgs4tegser4labnab");
container->AddAtBegining(planet);
}
for(int i=0; i<10000000; i++)
{
container->DeleteFromBegining();
}
cin>>i;
return 0;
}
planetarySystemContainer.hpp:
class PlanetarySystemContainer
{
private:
PlanetarySystem *First;
PlanetarySystem *Last;
int PlanetarySystemQuantity;
public:
PlanetarySystemContainer();
void AddAtBegining(PlanetarySystem *a);
void DeleteFromBegining();
};
planetarySystemContainer.cpp
#include"planetarySystemContainer.hpp"
PlanetarySystemContainer::PlanetarySystemContainer()
:First(NULL)
,Last(NULL)
,PlanetarySystemQuantity(0)
{
}
void PlanetarySystemContainer::AddAtBegining(PlanetarySystem *a)
{
a->SetPrevious(NULL);
a->SetNext(First);
First=a;
if(a->GetNext()==NULL)
Last=a;
PlanetarySystemQuantity++;
}
void PlanetarySystemContainer::DeleteFromBegining()
{
if(First!=NULL )
{
if(First->GetNext()!=NULL)
{
PlanetarySystem* x=First;
First=First->GetNext();
First->SetPrevious(NULL);
delete x;
}
else
{
PlanetarySystem* x=First;
First=NULL;
Last=NULL;
delete x;
}
PlanetarySystemQuantity--;
}
}
planetarySystem.hpp:
#include <iostream>
class PlanetarySystem
{
private:
PlanetarySystem* Next;
PlanetarySystem* Previous;
unsigned int PlanetQuantity; //ilosc obiektow w ukladzie (planet+stacji+asteroid)
public:
PlanetarySystem();
string name;
PlanetarySystem *GetNext();
PlanetarySystem *GetPrevious();
void SetNext(PlanetarySystem *ps);
void SetPrevious(PlanetarySystem *ps);
int GetPlanetQuantity();
};
planetarySystem.cpp:
#include "planetarySystem.hpp"
PlanetarySystem::PlanetarySystem()
:Next(NULL)
,Previous(NULL)
,PlanetQuantity(0)
{
}
PlanetarySystem *PlanetarySystem::GetNext()
{
return Next;
}
PlanetarySystem *PlanetarySystem::GetPrevious()
{
return Previous;
}
void PlanetarySystem::SetNext(PlanetarySystem *ps)
{
Next=ps;
}
void PlanetarySystem::SetPrevious(PlanetarySystem *ps)
{
Previous=ps;
}
int PlanetarySystem::GetPlanetQuantity()
{
return PlanetQuantity;
};
I see no leak on the first look. But you can easily give a planet a unique name based on its insertion loop number and print the name in the destructor.
This way you can test if all Planets get deleted.
I just ran your code on my Linux box with valgrind after fixing some compile-time errors and reducing the loop count to something reasonable. The only leak valgrind detected is the leaked PlanetarySystemContainer. You aren't deleting it before the program exits.
Regardless, and as I mentioned in my comment, why are you reinventing the wheel by creating a custom container? It seems to me the standard containers will meet your needs just as well. Lastly leverage things like std::unique_ptr<> to automate memory management, or simply store PlanetarySystem objects within the container rather than pointers to them to obviate the need to manage memory.
Related
There is a ""rumor"" that I've heard in the competitive programming community that an approach to implementing a data structure, for example, using classes would render a much slower time than an implementation basing itself on a purely functional paradigm. I've tested this out (on my recursive segment tree implementation using classes then only functions that were practically the same) with a completely random generator (the queries and the updates had an equal probability in appearing in the testcase), and the results concured with the hypothesis; the purely functional program averaged (~7 seconds) twice better than the object-oriented implementation (~12.8 seconds) in high (5 mil - 10 mil queries+updates) inputs.
So, my question is, why would this difference is so accentuated, and why does it even happen in the first place?
Thank you for reading this!
Here's the code(maybe I messed up something and that's why all of this happened):
The class implementation:
#include <iostream>
using namespace std; //poor practice :P
class AINT {
int tree[1048700];
public:
void update(int val, int poz, int node=1, int cl=1, int cr=500000) {
if(cl==cr) {
tree[node]=val;
return;
}
int mid=(cl+cr)/2;
if(poz<=mid)
update(val,poz,2*node,cl,mid);
else
update(val,poz,2*node+1,mid+1,cr);
tree[node]=max(tree[2*node],tree[2*node+1]);
}
int query(int l, int r, int node=1, int cl=1, int cr=500000) {
if(l<=cl && cr<=r) {
return tree[node];
}
int mid=(cl+cr)/2,a=0,b=0;
if(l<=mid)
a=query(l,r,2*node,cl,mid);
if(mid<r)
b=query(l,r,2*node+1,mid+1,cr);
return max(a,b);
}
}aint;
int main() {
int n;
cin >> n;
for(int i=0,t,x,y; i<n; i++) {
cin>> t >> x>> y;
if(t==1)
aint.update(y,x);
else
cout << aint.query(x,y) <<'\n'; // i added the output (which I then redirected to a file) because it seems relevant to also print the values (otherwise the compiler might just ignore the unused result)
}
return 0;
}
the purely functional implementation:
#include <iostream>
using namespace std;
int tree[1048700];
void update(int val, int poz, int node=1, int cl=1, int cr=500000) {
if(cl==cr) {
tree[node]=val;
return;
}
int mid=(cl+cr)/2;
if(poz<=mid)
update(val,poz,2*node,cl,mid);
else
update(val,poz,2*node+1,mid+1,cr);
tree[node]=max(tree[2*node],tree[2*node+1]);
}
int query(int l, int r, int node=1, int cl=1, int cr=500000) {
if(l<=cl && cr<=r) {
return tree[node];
}
int mid=(cl+cr)/2,a=0,b=0;
if(l<=mid)
a=query(l,r,2*node,cl,mid);
if(mid<r)
b=query(l,r,2*node+1,mid+1,cr);
return max(a,b);
}
int main() {
int n;
cin >> n;
for(int i=0,t,x,y; i<n; i++) {
cin>> t >> x>> y;
if(t==1)
update(y,x);
else
x=query(x,y); // i added the output (which I then redirected to a file) because it seems relevant to also print the values (otherwise the compiler might just ignore the unused result)
x=y+x*x;
}
return 0;
}
the generator:
#include <iostream>
using namespace std;
static int rand(int a, int b) {
return rand()%(b-a+1)+a;
}
int main(int argc, char * argv[]) {
srand(atoi(argv[1]));
int n;
n=10000000;
cout << n << '\n';
for(int i=0; i<n; i++) {
int t=rand(0,1),x=rand(1,500000),y=rand(1,500000);
if(t==0 && x>y)
swap(x,y);
cout << t << ' ' <<x << ' ' <<y <<'\n';
}
}
It depends if your class defines constructors or destructors or inherits from another class and especially if it uses inherited virtual functions like:
class Animal{
virtual void makeSound(){}
virtual std::string getName(){}
};
class Dog : Animal{
void makeSound(){}
std::string getName(){}
};
than there is overhead for using the virtual function table. I know for a fact that virtual destructors can really kill performance. However just moving a bunch of functions into a class will not hurt your performance at all.
It's also arguable that your example of 'pure functional' is not even close to the tag definition.
If you meant using a bunch of functions in the global namespace vs functions wrapped in class, there is no performance differences if you compile with -O3 optimizations or Release Mode on MSVC.
Although if your not going to use the features of classes and you just want a way to organize and find functions use a namespace like:
namespace animal {
namespace dog {
void bark() {}
}
}
animal::dog::bark();
Also please be careful how your measuring performance, if you're timing std::cout or std::cin you're going to get terrible numbers IO is always very slow and totally inconsistent.
You would never measure IO operations if you can help it. I suggest you watch this: https://www.youtube.com/watch?v=YG4jexlSAjc
by The Cherno a.k.a. Yan Chernokov , his tutorials are fantastic.
Note: Similar questions have been asked, but nearly all that I've found seem to make direct use of a pointer which may not be relevant here
For this snippet of code
#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;
class Unit{
public:
string name;
char value;
vector<Unit> inner;
Unit(string Name){
name=Name;
}
Unit(char Value){
name="Character";
}
};
class Instruction{
public:
int size;
string type;
string value;
map<string, vector<Unit>> vars;
vector<Instruction> inner;
vector<Instruction> outer;
Instruction(string Type,string Value,vector<Instruction>& Outer,map<string, vector<Unit>> &Vars){
type=Type;
value=Value;
outer=Outer;
vars=Vars;
size=0;
}
Instruction(string Type,vector<Instruction>& Outer,map<string, vector<Unit>> &Vars){
type=Type;
outer=Outer;
vars=Vars;
size=0;
}
bool matches(vector<Unit> &info,int position=0, int vectLocation=0){
cout<<value<<'\n'; //Segmentation Fault Occurs Here
return false;
}
};
void breakUp(vector<Unit>&u,string s){
for(int i=0;i<s.size();i++){
u.push_back(Unit(s[i]));
}
}
int main(){
//String to be matched
vector<Unit> v;
breakUp(v,"For the love of tests");
//Instruction Vector
vector<Instruction> i;
//Var Vector
map<string, vector<Unit>> x;
//Add initial instruction
Instruction constant("Constant","",i,x);
constant.inner.push_back(Instruction("String","For the love of tests",constant.inner,x));
//Test match
bool result=i[0].matches(v);
if(result==true){
cout<<"Match True\n";
}else{
cout<<"Match False\n";
}
return 0;
}
I get a segmentation fault when attempting to access one of the data members within the matches function. This also occurs when it attempts to print size or type. I have not been able to discern the exact cause of this memory issue and would appriciate any advice or considerations.
vector<Instruction> i;
...
bool result=i[0].matches(v);
i is empty, so accessing i[0] yields undefined behavior.
The reason for SIGSEGV seems to be
bool result=i[0].matches(v);
When you did
vector<Instruction> i;
A new std::vector object was created with size 0.
Now, when you try to access the first element by the above statement, it may give Segmentation fault.
Suggestion:
1) Use const std::string & instead of std::string in the constructor. Using std::string will lead to the string getting copied twice (which won't be good for performance).
I'm new to C++, so I decided to work on some little project to improve myself. I try to write a simple chess program with class Unit, and class King which is inherited from Unit
#include <list>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <stdlib.h> /* abs */
using namespace std;
// Each unit class represent a chess unit
class Unit{
protected:
int currentX;
int currentY;
string side;
public:
Unit();
Unit(string sideplay, int Xpos,int Ypos)
{
currentX=Xpos; currentY= Ypos;side=sideplay;
}
int getX()
{
return currentX;
}
int getY()
{
return currentY;
}
string getside()
{
return side;
}
void setpos(int newX,int newY) //set new position
{
currentX=newX;
currentY=newY;
}
bool validmove(vector<Unit> unitlist ,string sidepick,int Xpos,int Ypos)
{ int i=0;
while(i != 3)
{ int X=unitlist[i].getX();
int Y=unitlist[i].getY();
string sidetemp= unitlist[i].getside();
if ((X==Xpos)&&(Y==Ypos)&&(sidetemp==sidepick))
{
return false;
}
else if ((X==Xpos)&&(Y==Ypos)&&(sidetemp!=sidepick))
{ //unitlist[i]=NULL;
return true;
}
i++;
}
return true;
}
virtual void moveunit(vector<Unit> unitlist ,int nextX,int nextY);
};
class King: public Unit{
public:
King(string sideplay, int Xpos,int Ypos):Unit(sideplay,Xpos,Ypos)
{}
void moveunit(vector<Unit> unitlist ,int nextX,int nextY){
int diffX=abs(nextX-currentX);
int diffY=abs(nextY-currentY);
if ((diffX==1)||(diffY==1))
{ if (validmove(unitlist,side,nextX,nextY))
{
setpos(nextX,nextY);}
}
}
};
and here is my main:
int main()
{
vector<Unit> chessunit;
chessunit.push_back(King("white",3,1));
chessunit.push_back(King("black",3,2));
chessunit.push_back(King("white",4,1));
if (chessunit[0].validmove(chessunit,"white",3,2))
{
cout<<"hehe"<<endl;
}
chessunit[0].moveunit(chessunit,3,2);
int k= chessunit[0].getY();
cout<<k<<endl;
return 0;
}
I keep getting LNK 2001 error: Unresolved external symbol for my virtual method "moveunit". How can I fix that bug ?
The easiest way of fixing your problem is using pointers or smart pointers: Store vector<Unit*>, vector<std::shared_ptr<Unit>> or vector<std::unique_ptr<Unit>> (thanks #rubenvb) instead of vector<Unit> and then add your kings like so:
myVector.push_back(new King...); // or
myVector.push_back(std::shared_ptr<King>(new King...)); // or
myVector.push_back(std::unique_ptr<King>(new King...));
Why?
If you allocate an object of a virtual class (e.g. Unit unit) and you want to assign an object of an implementation of that class to it, e.g.:
Unit unit;
unit = King(...);
Then you will get an error, or at least run into trouble, unless you provide a constructor for Unit that takes King as an argument or provide a sufficient move operator. That is because if you try to assign an object of a type that is not Unit to unit, the compiler and/or run-time (depending on what the back-end of your compiler is) will have a tough time figuring out how compatible the types are and what to do if things "don't fit" memory-wise and how to cope with memory layout issues.
Further Reading
For more on pointers vs. smart pointers, consider this thread. Also here is a related Stackoverflow question and an article on using shared_ptr with STL collections
More information on trying to "squeeze" an object of one type into another (called slicing) can be found in this thread.
The problem you are facing right now is due to slicing: when you add a King to the vector, it gets sliced into an instance of Unit.
One way to fix this is to turn chessunit into a vector of std::shared_ptr<Unit> and allocate units on the heap.
P.S. Since you are not defining Unit::moveunit(), make it pure virtual:
virtual void moveunit(vector<Unit> unitlist ,int nextX,int nextY) = 0;
^^^
I am stuck on the output member function of the class. I have no idea how to create it and just simply couting it does not seem to work. also any other advice would be great. thanks in advance
here's the code:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class StringSet
{
public:
StringSet(vector<string> str);
void add(string s);
void remove(int i);
void clear();
int length();
void output(ostream& outs);
private:
vector<string> strarr;
};
StringSet::StringSet(vector<string> str)
{
for(int k =0;k<str.size();k++)
{
strarr.push_back(str[k]);
}
}
void StringSet::add(string s)
{
strarr.push_back(s);
}
void StringSet::remove(int i)
{
strarr.erase (strarr.begin()+(i-1));
}
void StringSet::clear()
{
strarr.erase(strarr.begin(),strarr.end());
}
int StringSet::length()
{
return strarr.size();
}
void StringSet::output()
{
}
int main()
{
vector<string> vstr;
string s;
for(int i=0;i<10;i++)
{
cout<<"enter a string: ";
cin>>s;
vstr.push_back(s);
}
StringSet* strset=new StringSet(vstr);
strset.length();
strset.add("hello");
strset.remove(3);
strset.empty();
return 0;
}
Ok, you should begin by solving some errors in your code:
You use a pointer to StringSet and after that you are trying to access the member-functions with the . operator instead of the ->. Anyway, do you really need to allocated your object dynamically ?
StringSet strset(vstr); // No need to allocated dynamically your object
After that, you are calling an empty() method which does not exist...
Also if you stay on dynamic allocation, don't forget to deallocated your memory :
StringSet* strset = new StringSet(vstr);
// ...
delete strset; // <- Important
Finally, I think that your function output should write in the stream the content of your vector, you can do it that way :
#include <algorithm> // For std::copy
#include <iterator> // std::ostream_iterator
void StringSet::output( ostream& outs )
// ^^^^^^^^^^^^^ don't forget the arguments during the definition
{
std::copy(strarr.begin(), strarr.end(), std::ostream_iterator<string>(outs, "\n"));
}
HERE is a live example of your code fixed.
I would suggest you to understan how class works : http://www.cplusplus.com/doc/tutorial/classes/
If your output function is going to print the state of the StringSet object, you may implement is like this:
#include<iterator> //std::ostream_iterator
#include<algorithm> //std::copy
void StringSet::output(ostream& outs)
{
std::copy(starr.begin(), starr.end(), std::ostream_iterator<string>(outs, "\n"));
}
I have this code
main.cpp
#include <iostream>
#include "functs.h"
using namespace std;
int main()
{
ArrayList *al = new ArrayList;
return 0;
}
functs.h
using namespace std;
#ifndef FUNCTS_H_INCLUDED
#define FUNCTS_H_INCLUDED
class ArrayList;
#endif // FUNCTS_H_INCLUDED
functs.cpp
#include <iostream>
#include "functs.h"
class ArrayList{
public:
void add(int num);
void add(int num, int index);
void remove(int index);
void removeNum(int num);
string toString();
ArrayList(int init);
private:
void resize();
int size, cap;
int *myList[10];
};
void ArrayList::add(int num){
if (size>=cap/2)
{
resize();
}
*myList[size] = num;
size++;
}
void ArrayList::resize(){
int temp[cap*2];
int i;
for (i = 0; i < size; i++)
{
temp[i] = *myList[i];
}
*myList = temp;
}
ArrayList::ArrayList(){
size = 0;
cap = 10;
}
void ArrayList::add(int num, int index){
int temp = *myList[index];
int i;
for (i = index; i < size; i++)
{
*myList[index] = num;
num = temp;
temp = *myList[i+1];
}
add(temp);
}
string ArrayList::toString(){
string returnString = "{";
int i;
for (i = 0; i < size; i++)
returnString.append(*myList[i] +",");
returnString.replace(returnString.length()-1,1,"}");
return returnString;
}
and I'm extremely new to C++ but whenever I try to compile the code it gives me a "size of ArrayList is not know". Please help me figure out the error. =(
Design/usage problems in your code notwithstanding, the most obvious problem is that you want to put the class definition in the functs.h file instead of the functs.cpp file:
functs.h:
// This is declaration is highly not recommended for use in header files.
// using namespace std;
#ifndef FUNCTS_H_INCLUDED
#define FUNCTS_H_INCLUDED
#include <string>
class ArrayList{
public:
void add(int num);
void add(int num, int index);
void remove(int index);
void removeNum(int num);
std::string toString();
ArrayList(int init);
private:
void resize();
int size, cap;
int *myList[10];
};
#endif // FUNCTS_H_INCLUDED
functs.cpp:
#include "functs.h"
void ArrayList::add(int num){
if (size>=cap/2)
{
resize();
}
*myList[size] = num;
size++;
}
void ArrayList::resize(){
int temp[cap*2];
int i;
for (i = 0; i < size; i++)
{
temp[i] = *myList[i];
}
*myList = temp;
}
ArrayList::ArrayList(){
size = 0;
cap = 10;
}
void ArrayList::add(int num, int index){
int temp = *myList[index];
int i;
for (i = index; i < size; i++)
{
*myList[index] = num;
num = temp;
temp = *myList[i+1];
}
add(temp);
}
std::string ArrayList::toString(){
std::string returnString = "{";
int i;
for (i = 0; i < size; i++)
returnString.append(*myList[i] +",");
returnString.replace(returnString.length()-1,1,"}");
return returnString;
}
templatetypedef provides a reason why this is necessary. Basically the compiler needs to know how much space an ArrayList needs, and a class ArrayList; provides no such information.
It's not a good idea to declare using namespace std; inside a header file, because then everyone that includes the functs.h file (including your clients!) will also have a using namespace std;, increasing the possibility of name collisions.
I highly recommend that you pick up a good introductory C++ book if you wish to learn C++ properly. You demonstrate in your question a rather big misunderstanding of how good C++ is written. That's not to say you're incompetent as a person, but there are some serious problems with the code you present. Just to name a few:
Standard C++ already provides a perfectly fine array class called std::vector. There's no need to reinvent the wheel for what you're doing. And even if you have to reinvent the wheel, an advanced understanding of C++ and plenty of C++ experience is a prerequisite to implementing an array container that's appropriate for production use.
The public interface of your class is incomplete. There's no way for clients to know how many elements are actually in the array.
int *myList[10]; declares a fixed array of 10 pointers to an int. This is not appropriate for an array class. Especially if you want the array to be resizable.
There's not sufficient memory management for this class to be useful in any sense. There are no destructors and apparently the constructors are not complete (nor do they match), so you have no real logical place to put things like new[] and delete[].
You have a ArrayList *al = new ArrayList; but you don't have a corresponding delete al; anywhere. This is a memory leak.
But the last point is moot because you should be using ArrayList a1; instead of ArrayList *al = new ArrayList;. The former will automatically "delete" itself at the end of the scope (in this case, the main() function) while the latter requires a delete statement. C++ is not like Java where unused new'ed objects are automatically collected.
I can't comment on the correctness of the algorithms you used, because (and I'm sorry to say this because it'll sound harsh) what you have simply won't work. Again, I recommend that you pick up a good introductory C++ book, which will cover these kinds of issues. (I must emphasize that none of these shortcomings are a statement of you as a person. I'm talking specifically about the code you have in your question.)
The reason that you're getting this error is that in main.cpp, the compiler hasn't seen the definition for the class ArrayList. It's only seen the declaration
class ArrayList;
When you try to create the ArrayList by writing
new ArrayList;
The compiler doesn't know how much memory is needed to hold an ArrayList because it hasn't seen the class definition. This contrasts with other languages like Java, where this information doesn't have to immediately be available.
To fix this, update your .h file by moving the definition of the class from the .cpp file. That way, when someone #includes the header file, they'll get the class definition in addition to the declaration, which will allow you to use new, declare local variables of type ArrayList, etc.
Hope this helps!
This much
class ArrayList{
public:
void add(int num);
void add(int num, int index);
void remove(int index);
void removeNum(int num);
string toString();
ArrayList(int init);
private:
void resize();
int size, cap;
int *myList[10];
};
Should be in the .h file.
Why? Because the declaration of a class (when you write class ArrayList;) is only enough when the size of the class is not needed (more specific cases are listed in the C++ standard). The definition of the class should appear in the same translation unit in which the class is used in a way in which it is required to be complete.
The way you've declared myList it has a fixed size; *myList = temp; isn't doing what you want it to.
Declare myList simply as int *myList;
In the constructor, use myList = new int[10];
Everywhere you have *myList[...] change it to myList[...]
In resize, int temp[cap*2] needs to be int *temp = new int[cap * 2] and *myList = temp needs to be myList = temp
You'll still have a memory leak, but that should get you started.