Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I was trying to program my own List class on C++.
Here is the code:
template <class T>
class List
{
private:
T *value, *valueHelper;
int valueSize;
public:
int size;
List()
{
valueSize = 2;
value = new T[valueSize];
size = 0;
}
void Add(T val)
{
size++;
if (size > valueSize)
{
valueSize *= 2;
valueHelper = new T[valueSize];
memcpy(valueHelper, value, sizeof(T) * (size - 1));
delete[](value);
value = valueHelper;
}
value[size - 1] = val;
}
void Clear()
{
delete[](value);
size = 0;
valueSize = 2;
value = new T[valueSize];
}
T & operator[](int P)
{
return value[P];
}
};
The problem appered when I used a class variable on this List Class.
When I do Clear to delete some memory, there are a run time error appers.
I have trying to check what cause this problem and I have find out that this line on the function Clear() is the error line:
delete[](value);
I can not understand, why?
I'm just guessing here, but it could be likely it is because you will have copies made of the List instance, for example by returning it from a function or passing it as a non-reference argument to a function.
Copying of objects are implemented by the default copy-constructor generated by the compiler, but it only does shallow copying, meaning it will copy the pointers but not what they point to. So then you will have two copies with pointers pointing to the same memory, and when one object deletes that memory the others pointer will be invalid.
You also have a memory leak in that you don't have a destructor, so when an instance goes out of scope then you loose the allocated memory forever.
You should also read about the rule of three.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed last year.
This post was edited and submitted for review last year and failed to reopen the post:
Original close reason(s) were not resolved
Improve this question
this is the code i have for deep copying a string in copy constructor
so is the logic correct??I think there may be memory leak and i am trying to fix that.m.pStatus is initialised
class Monkey
{
public:
// insert your code here
Monkey();
Monkey(const Monkey& m);
Monkey& operator=(const Monkey& m);
~Monkey();
// accessors
int getX();
int getY();
char *getStatus();
void deepCopy(const Monkey& m);
// global variables (incremented each creation or destruction)
static int numStringsCreated;
static int numStringsDestroyed;
private:
// Do not change this data
int x;
int y;
char *pStatus;
};
void Monkey::deepCopy(const Monkey& m)
{
if (m.pStatus)
{
// allocate memory for our copy
pStatus= new char[sizeof(m.pStatus)];
for (int i{ 0 }; i < sizeof(m.pStatus); ++i)
pStatus[i] = m.pStatus[i];
}
else
pStatus = nullptr;
}
Monkey::Monkey(const Monkey& m)
{
deepCopy(m);
numStringsCreated++;
}
Avoid using sizeof(pStatus). Unless the variable is fixed sized array, it will evaluate to the size of a pointer, not the length of the string.
strlen and strcpy for classic C string length and copy operations.
This is closer to what you want. It ensures that it cleans up any previous allocation and implicitly handles the case where a self assignment is made (e.g. m.deepCopy(m)) by allocating the copy first before deleting the old. You could make an additional optimization to say if (m.pStatus == pStatus) and skip the copy operation entirely.
I'm working under the assumption that pStatus was initialized to null or something valid in the constructor.
void Monkey::deepCopy(const Monkey& m)
{
char* psz = nullptr;
if (m.pStatus)
{
size_t len = strlen(m.pStatus);
psz = new char[len+1]; // +1 for null char
strcpy(pStatus, m.pStatus);
}
delete [] pStatus;
pStatus = psz;
}
But if pStatus was a std::string you wouldn't need to do any of this allocation stuff and you likely wouldn't need to overload the assignment operator or copy constructor.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 6 years ago.
Improve this question
When I'm learning data structure at the binomial heap, I read Weiss's code implementation. Some code as follow:
node implementation and deleteMin algorithm are like:
template<typename Comparable>
struct BinomialNode
{
Comparable element;
BinomialNode *leftChild;
BinomialNode *nextSibling;
};
void deleteMin( Comparable & minItem )
{
int minIndex = findMinIndex( );
minItem = theTrees[ minIndex ]->element;
BinomialNode *oldRoot = theTrees[ minIndex ];
BinomialNode *deletedTree = oldRoot->leftChild;
delete oldRoot;
}
But I'm confused by the "Comparable & minItem". As we see, the "minItem" saves the element. But soon the "oldRoot" has been deleted! The "element" member is inside of the "oldRoot"! Can someone tell me the principle of the status...
I also made some other tests.
struct Node{
int i;
Node * next;
Node(int i, Node* next = nullptr): i(i), next(next){}
};
void getInt(int & i){
int * p = new int(3);
i = *p;
delete p; //the reference can get the true value??? =>output: 3(right)
}
void getInt(int * &i){
int * p = new int(3);
i = p;
delete p; //pointer can't get the real number because of deletion => output: 6904432(wrong)
}
int main() //for test
{
Node* child = new Node(3);
Node* root = new Node(1, child);
int i;
getInt(i);
cout << i << endl;
int * m;
getInt(m);
cout << *m;
}
I've learnt about the bottom implementation of the reference & is the point *.
But why & can get the real value... I feel confused. Thx!!
If you ask whether there is something wrong with the the binomial code, then the answer is no, there is nothing wrong with assigning to the parameter.
In the first code, minItem = theTrees[ minIndex ]->element; copies the object to the object that is passed as reference, so afterwards there is no reference to anything that was deleted (assuming Comparable has no knowledge of BinomialNode). The reference of the parameter refers to the passed object not to anything in the data-structure.
The same goes for the test: after getInt(i), int just contains 3.
However, void getInt(int * &i) returns a dangling pointer, so this is bad code.
Edit out of completeness: the answer was addressing the assumed issue with the reference parameter, but the binomial code void deleteMin( Comparable & minItem ) contains 2 issues, hopefully addressed later in the book:
the case where findMinIndex() fails isn't handled. What happens with an empty heap?
BinomialNode *deletedTree = oldRoot->leftChild;: nothing is done with deletedTree, which at least causes a memory leak and actually loses information.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Pseudocode, I don't know if this compiles or not, but you get the idea.
class DataHolder
{
void GetData(float* ptr)
{
ptr = dataNeededByOtherClass;
}
float* dataNeededByOtherClass; // Initialized and modified elsewhere
};
class DataUser
{
void DoStuff()
{
float* ptrToData;
dataHolder->GetData(ptrToData);
// ptrToData points to garbage Why?
ptrToData = dataHolder->dataNeededByOtherClass;
// ptrToData now points to the correct data
}
};
What am I looking at here?
The function
void GetData(float* ptr)
receives the pointer argument by value. Modifying ptr within the function does not change the value of ptrToData. Instead, try to pass a pointer by pointer:
void GetData(float** ptrptr)
{
*ptrptr = dataNeededByOtherClass;
}
float* ptrToData;
dataHolder->GetData(&ptr);
P.S. Please note that exposing class variables in such a way is not considered as best practice.
Hi there are several syntax errors in your code. The code below doesn't add constructors and destructors as you mention them in your text above. Your data needs to come from somewhere :) I took the libery of creating a SetData method below. Note that I also free the memory of your buffer in both the destructor and when you set the pointer, if the pointer is not null. If you don't want this just cut it away :)
Working Code
class DataHolder
{
private:
float* dataNeededByOtherClass; // Initialized and modified elsewhere
public:
float* GetData()
{
return dataNeededByOtherClass;
}
void SetData(float* ptr)
{
// Remove if you intend to keep this memory and release it elsewhere
if (dataNeededByOtherClass != NULL)
delete[] dataNeededByOtherClass;
dataNeededByOtherClass = ptr;
}
// You are missing constructors and destructors
DataHolder() : dataNeededByOtherClass(NULL){};
DataHolder(float *ptr) : dataNeededByOtherClass(ptr){};
~DataHolder()
{
// if you want to release data after class is destructed.. if not remove these lines
if (dataNeededByOtherClass != NULL)
delete[] dataNeededByOtherClass;
};
}
class DataUser
{
void DoStuff()
{
DataHolder dataHolder; // either feed data in c'tor or use dataHolder->SetData() for filling data, now it's just empty..
float* ptrToData = dataHolder.GetData();
}
};
Hope it helps.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
There is a part of my class, which I'm using to read data, byte by byte, until '\0' occur.
RESULT MyClass::readMethod(DataInputStream& s)
{
if ( condition = ok )
{
char tmp[32];
uint8 i = 0;
do {
tmp[i] = s.read_int8();
} while (tmp[i++] == '\0');
char *arr= new char[i];
for (uint8 j = 0; j < i; ++j)
{
arr[j] = tmp[j];
}
//delete[] arr;
}
}
I removed a lot of code for this post, since rest is less important.
My problem is, that I want to free up memory, but since I've got method:
I tried put it into destructor:
MyClass::~MyClass()
{
delete [] arr;
}
but compiler (I use Visual Studio 2010) underline it and says: "Error: identifier arr is undefined".
I can't use it in place where it is commented, because I've got following method:
char * getArr()
{
return arr;
}
But tbh, I don't know if it will work, I mean, if I can access arr outside the class. Im still learning C++ and OOP, and sometimes I'm confused.
Similiar problem is with constructor: how to initialize arr to be empty.
Your arr is local to readMethod. So the destructor does not know it. You have to declare arr as a class member.
class MyClass
{
private:
char* arr;
}
Then you can delete it in your destructor.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 8 years ago.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Improve this question
I'm currently working on a game using OpenGL ES 2.0 on Android (in C++ using the NDK).
I have a class called "Drawable" which is my base class for drawing objects using OpenGL.
In the destructor of the class I have to clean up some buffers :
Drawable::~Drawable() {
LOGE("release");
releaseBuffers();
}
But the destructor is called endlessly (as in every loop of the thread), which messes up my drawing.
I'm kind of lost here and I could not find similar problems, so help is welcome!
Edit: Loop code is here : link
Edit2: I found one of the evil calls:
In my player class I have this call:
currentWeapon->draw(this);
to
void Weapon::draw(Player* p)
If I comment this, the spam is gone.
There are very few ways a destructor gets called:
1) You create an instance of Drawable on the stack, and it falls out of scope. If this is done in a tight loop, the object will fall out of scope and be destroyed at each iteration of the loop. For example:
for (size_t i = 0; i < 100; ++i)
{
Drawable d;
}
Here, 100 instances of Drawable will be created and destroyed, at the beginning and end of every loop.
2) You delete a dynamically-allocated Drawable:
for (size_t i = 0; i < 100; ++i)
{
Drawable* d = new Drawable;
delete drawable;
}
3) You call the destructor explicitly:
Drawable* b = new (buffer) Drawable;
b->~Drawable()
Note that #3 uses "placement new" and is highly unlikely.
Objects can be destroyed at suprising times when they are in a container such as a vector. Consider:
vector <Drawable> drawables;
for (size_t i = 0; i < 10000; ++i)
{
Drawable d;
drawables.push_back (d);
}
You will notice potentially many destructor calls when you run this code. When you push_back, a copy is potentially made and the original (d here) is destroyed. Also, when the vector reaches capacity it has to reallocate, which results in every item being copied again, and the originals destroyed.
Objects can also be destroyed at suprising time in the face of temporaries and unexpected copies. Consider:
void DoSomething (Drawable d)
{
}
int main()
{
Drawable d;
for (size_t i = 0; i < 1000; ++i)
{
DoSomething (d);
}
}
This is a naive example because the compiler will likely elide the temporaries in this case. But since DoSomething() takes a Drawable by-value a copy of the original could be made. Depending on other code, the compiler might not even be able to elide this copy.