Memory for array property not allocated before Constructor? - c++

When I run the program and new a NetworkEditor, it will corrupt at the constructor because of it reads out of the array's memory.
When I debug it one loop by one loop, it will be ok!?
Why? Didn't it allocate enough memory for the array before it entered the constructor?
In my class, I have two properties:
/*NetworkEditor.h*/
class CNetworkEditor : public CDiagramEditor
{...
VLLink* VL_list[10];
VLLink* temp_VL_list[10];
}
and in the constructor, I initialize the arraies:
/*NetworkEditor.cpp*/
for (int i = 0; i < 10; i++)
{
VLLink* vl_link = NULL;
while(vl_link == NULL)
{
vl_link = new VLLink;
}
vl_link->preLink = NULL;
vl_link->nextLink = NULL;
vl_link->link = NULL;
VLLink* vl_link2 = NULL;
while (vl_link2 == NULL)
{
vl_link2 = new VLLink;
}
vl_link2->preLink = NULL;
vl_link2->nextLink = NULL;
vl_link2->link = NULL;
VL_list[i] = vl_link;
temp_VL_list[i] = vl_link2;
}
and VLLink is defined as:
typedef struct struct_VLLink
{
CPhysicalLink* link;
struct_VLLink* preLink;
struct_VLLink* nextLink;
}VLLink;
If I change it to:
VLLink* VL_list2[10];
VLLink* temp_VL_list2[10];
for (int i = 0; i < MAX_VL_NUM; i++)
{
VLLink* vl_link = NULL;
while(vl_link == NULL)
{
vl_link = new VLLink;
}
vl_link->preLink = NULL;
vl_link->nextLink = NULL;
vl_link->link = NULL;
VLLink* vl_link2 = NULL;
while (vl_link2 == NULL)
{
vl_link2 = new VLLink;
}
vl_link2->preLink = NULL;
vl_link2->nextLink = NULL;
vl_link2->link = NULL;
VL_list2[i] = vl_link;
temp_VL_list2[i] = vl_link2;
}
It will be ok!?

Apart from #PeterHuene's suggestion to replace VL_list and temp_VL_list with something like std::list<CPhysicalLink> or similar, you should move the initialization of VLLink into the constructor, avoiding the code duplication in your loop
struct VLLink {
VLLink() : link(NULL), prelink(NULL), nextlink(NULL) {}
...
};`
then you can reduce your loop as #MikeSeymour said
for (int i = 0; i < MAX_VL_NUM; i++) {
VL_list[i] = new VLLink();
temp_VL_list[i] = new VLLink();
}
A reason for your memory problem might be, that MAX_VL_NUM is larger than 10. So, you should either use MAX_VL_NUM everywhere or use 10 everywhere.
And now to your question ;-)
If I change it to ... It will be ok!?
Nobody can answer this, because nobody knows what you want to achieve. My first reaction would be definitely No!, because moving variables around "just because" is almost always a bad idea. It's better to analyze the problem and fix the cause than to cure some random symptoms.
Your change would also modify the meaning from member of a class to automatic variable on the stack.

Related

How to fix memory leak

I am working on the project which using pointer (new ext...) and I don't know how to fix it, I couldn't use the delete syntax because it will break the code literally.
list<Virus*> DoClone()
{
list<Virus*> l;
Dengue *d1 = new Dengue(1), *d2 = new Dengue(1);
for (int i = 0; i < 4; i++)
d1->m_protein[i] = m_protein[i];
d1->m_dna = m_dna;
d1->m_resistance = m_resistance;
for (int i = 0; i < 4; i++)
d2->m_protein[i] = m_protein[i];
d2->m_dna = m_dna;
d2->m_resistance = m_resistance;
l.emplace_back(d1);
l.emplace_back(d2);
//delete d1;
//delete d2;
return l;
}
void DoDie()
{
this->m_dna = NULL;
memset(this->m_protein, 0, 4);
this->m_resistance = 0;
delete this->m_dna;
}
Smart pointers to the rescue:
list<std::unique_ptr<Virus>> DoClone()
{
list<std::unique_ptr<Virus>> l;
auto d1 = std::make_unique<Dengue>(1);
auto d2 = std::make_unique<Dengue>(1);
for (int i = 0; i < 4; i++)
d1->m_protein[i] = m_protein[i];
d1->m_dna = m_dna;
d1->m_resistance = m_resistance;
for (int i = 0; i < 4; i++)
d2->m_protein[i] = m_protein[i];
d2->m_dna = m_dna;
d2->m_resistance = m_resistance;
l.emplace_back(std::move(d1));
l.emplace_back(std::move(d2));
return l;
}
void DoDie()
{
m_dna.reset();
memset(this->m_protein, 0, 4);
this->m_resistance = 0;
}
It would be best if you learn to use smart pointers ASAP. Here is good lecture on topic.
Also see:
C++ Core Guidelines
R.20: Use unique_ptr or shared_ptr to represent ownership
Reason
They can prevent resource leaks.
Example
Consider:
void f()
{
X x;
X* p1 { new X }; // see also ???
unique_ptr<X> p2 { new X }; // unique ownership; see also ???
shared_ptr<X> p3 { new X }; // shared ownership; see also ???
auto p4 = make_unique<X>(); // unique_ownership, preferable to the explicit use "new"
auto p5 = make_shared<X>(); // shared ownership, preferable to the explicit use "new"
}
This will leak the object used to initialize p1 (only).
Enforcement
(Simple) Warn if the return value of new or a function call with return value of pointer type is assigned to a raw pointer.
Extra:
small refactor:
std::unique_ptr<Dengue> createDengue(int x)
{
auto d = std::make_unique<Dengue>(x);
d->m_protein = m_protein; // someone claims this is an std::array so loop is not needed
d->m_dna = m_dna;
d->m_resistance = m_resistance;
return d;
}
list<std::unique_ptr<Virus>> DoClone()
{
list<std::unique_ptr<Virus>> l;
l.emplace_back(createDengue(1));
l.emplace_back(createDengue(1));
return l;
}
void DoDie()
{
m_dna.reset();
this->m_protein = {}; // someone claims this is an std::array so this is fine
this->m_resistance = 0;
}
list<Virus*> DoClone()
{
//Why are you using a list of pointers?
//Are you handing these out?
list<Virus*> l; // Replace list<Virus> l or use smart pointers
Dengue *d1 = new Dengue(1), *d2 = new Dengue(1);
for (int i = 0; i < 4; i++){
d1->m_protein[i] = m_protein[i];
}
//if the move semantics of any of them are wrong your code will crash,
//but you don't show us what these are.
d1->m_dna = m_dna;
d1->m_resistance = m_resistance;
for (int i = 0; i < 4; i++)
d2->m_protein[i] = m_protein[i];
d2->m_dna = m_dna;
d2->m_resistance = m_resistance;
l.emplace_back(d1);
l.emplace_back(d2);
//You definitely shouldn't be deleting these you jsut gave them to a container to hold!
//delete d1;
//delete d2;
return l;
}
void DoDie(ist<Virus*>& myList)
{
//You set this to nullptr, but try to delete it in 4 lines time. This looks like a leak
//Also the fact it was a pointer means you definitely copied it wrong above
//use std::shared_ptr or std::weak_ptr if you want to share things.
this->m_dna = NULL;
memset(this->m_protein, 0, 4);
this->m_resistance = 0;
delete this->m_dna;
//Lastly you need to free the memory in your container
for(auto* item : myList){
delete item;
}
myList.clear();
}

How to affect memory allocated by new and casted to an array od class objects?

I had hard time describing it in the title, but basically I have to turn some code from C based on structures into C++ one based on objects. At the beginnig it was more or less (I'll try to simplify since it's a part of a big library-like project):
typedef struct Thing{
int param;
char* name;
void* data; //Either some arrays or more structures, hence void*
};
Thing* Initialise(void){
Thing* thing;
thing = (Thing*)malloc(sizeof(*thing));
param = 0;
name = NULL;
data = NULL;
return thing;
}
Thing* thing1 = malloc(bytesofdata);
Thing** smallthings = (Thing**) thing1->data; //Basically if "data" is a structure of other things
for ( i = 0; i < numberofsmallthings; i++ ) {
size_t k;
for ( k = 0; k < fieldsperthing; k++ ) {
smallthings[i*fieldsperthing+k] = Initialise();
}
}
Then I turned the structure into a class and the function into its method which resulted in:
class Thing{
private:
int param;
char* name;
void* data; //Either some arrays or more structures, hence void*
public:
int Initialise(void);
};
int Thing::Initialise(void){
this->param = 0;
this->name = NULL;
this->data = NULL;
}
thing1->data = new Thing;
this->data = new char [bytesofdata];
Thing** smallthings = (Thing**)this->data;
for (i = 0; i < numberofsmallthings; i++) {
size_t k;
for (k = 0; k < fieldsperthing; k++) {
smallthings[i*fieldsperthing + k]->Initialise();
}
}
And in this version, no matter if I try initialising the memory of not I am greeted by "access violation".
Is there any way to make this work? Casting to structure seemed to work fine so my guess is that something about objects makes it not work but I have no idea how to potentially bypass this. I would like to avoid making more objects since due to this part being buried pretty deep in functions, deleting those would be quite hard (especially since it's supposed to be a data reading function so exact structure of "data" might be not known).
When you do this:
smallthings[i*fieldsperthing + k]->Initialise();
You're attempting to dereference an unintialized pointer. You first need to assign something to it, then you can initialize it:
smallthings[i*fieldsperthing + k] = new Thing;
smallthings[i*fieldsperthing + k]->Initialise();
Better yet, change Initialise to a constructor. Then you won't have to do creation and initialization in separate steps. So now you have:
int Thing::Thing(){
this->param = 0;
this->name = NULL;
this->data = NULL;
}
...
thing1 = new Thing();
this->data = (void *)new Thing *[numberofsmallthings];
Thing** smallthings = (Thing**)this->data;
for (i = 0; i < numberofsmallthings; i++) {
size_t k;
for (k = 0; k < fieldsperthing; k++) {
smallthings[i*fieldsperthing + k] = new Thing();
}
}

Memory leak with lists c++

The idea of the function is to divide the original list in X Lists all gather in a single array without delete nor creating new Cells.
The function do his job great but when I check the leaks with valgrind or Dr. Memory, It appears to have some leak problems...
List* function (List & todivide, int t = 2){
Cell* aux = todivide.l; // l is the head of the list
int tam = (todivide.size()/t == 0) ? todivide.size()/t : todivide.size()/t+1;
List* arrayoflists = new List [tam];
for(int i = 0, k = 0; aux != 0; i++){
if(i%t == 0){
arrayoflists[k].l = aux;
aux = aux->sig;
k++;
}
if(i%t == t-1){
Cell* p = aux->sig;
aux->sig = 0;
aux = p;
}
}
l.l = 0;
return arrayoflists;
}
I see nothing wrong... Any ideas?
Thanks in advance
There's nothing wrong inside the function but since you're returning a pointer that you created using new, you might be forgetting to delete the returned pointer where ever you're using it outside the function.

Deleting objects on the heap which store data on the heap

My program has been written using classes from the SDL library.
I have the following class:
class s_group
{
private:
SDL_Surface* image;
unsigned int* F_total;
float* F_length;
SDL_Rect** F;
float* F_current;
unsigned int S_total;
unsigned int S_current;
public:
s_group(void);
virtual ~s_group(void);
bool setup( const char* filename, unsigned int s );
//other member functions
};
Private member pointers each store the location of memory declared on the heap, as allocated by the member function setup.
bool s_group::setup( const char* filename, unsigned int s )
{
s_group::~s_group();//delete already allocated heap memory
if(!load_file(image, filename))
{
image = NULL;
return false;
}
S_total = s;
F = new SDL_Rect*[S_total];
F_total = new unsigned int[S_total];
F_length = new float[S_total];
F_current = new float[S_total];
for(unsigned int index = 0; index < S_total; ++index)
{
F[index] = NULL;
F_total[index] = 0;
F_length[index] = 0.f;
F_current[index] = 0.f;
}
//loop for each array slot and set values of data
return true;
}
Within a large function I create an object of this class on the heap, storing its address in an s_group pointer named sparkle.
s_group* sparkle = new s_group;
sparkle->setup("sparkle_final.png", 1 );
On completion of the function I call delete to reallocate the heap memory. Removing this line solves the problem, however there would then be a memory leak.
delete sparkle;
sparkle = NULL;
This will call the destructor of the class which is where I believe the error occurs due to an internal use of the delete operator.
s_group::~s_group(void)
{
SDL_FreeSurface(image);
image = NULL;
for(unsigned int s = 0; s < S_total; ++s)
{
for(unsigned int f = 0; f < F_total[s]; ++f)
{
F[s][f].x = 0;
F[s][f].y = 0;
F[s][f].w = 0;
F[s][f].h = 0;
}
delete[] F[s];
F[s] = NULL;
}
delete[] F;
F = NULL;
delete[] F_total;
F_total = NULL;
delete[] F_length;
F_length = NULL;
delete[] F_current;
F_current = NULL;
S_total = 0;
S_current = 0;
}
On reaching the delete operator, a dialog box appears stating:
Windows has triggered a breakpoint in Program.exe. This may be due to a corruption of the heap, which indicates a bug in Program.exe or any of the DLLs it has loaded.
How do I delete this object without causing the heap corruption?
From effective C++ Scott Meyers
Item 9: Never call virtual functions during construction or destruction.
You shouldn't call virtual functions during construction or destruction, because the calls won't do what you think, and if they did, you'd still be unhappy. If you're a recovering Java or C# programmer, pay close attention to this Item, because this is a place where those languages zig, while C++ zags.
Actually, even though you should define your destructor, calling it forcibly should be out of the question
I'm unable to compile your code but here goes..
The first thing I noticed was that you called your destructor.. You don't want to do that! Instead, create a release function and call that.
The next thing I noticed is that there is no FRAME variable within the class itself.. so this line:
FRAME = new SDL_Rect*[S_total];
is going to cause a compilation error and your destructor uses FRAME but no such variable exists. I think you meant to change it to F because if not, then this line:
F[index] = NULL;
is undefined behaviour since F is uninitialized..
Also, you never initialized each index of FRAME and so accessing it in the destructor like:
FRAME[s][f].x = 0;
is a no-no.
Again, you call
delete[] F;
F = NULL;
but F has no memory allocated and is uninitialized.
Thus with all the patches I think:
class s_group
{
private:
SDL_Surface* image;
unsigned int* F_total;
float* F_length;
SDL_Rect** FRAME;
float* F_current;
unsigned int S_total;
unsigned int S_current;
void Release();
public:
s_group(void);
virtual ~s_group(void);
bool setup(const char* filename, unsigned int s);
//other member functions
};
bool s_group::setup(const char* filename, unsigned int s)
{
Release();//delete already allocated heap memory
if(!load_file(image, filename))
{
image = NULL;
return false;
}
S_total = s;
FRAME = new SDL_Rect*[S_total];
F_total = new unsigned int[S_total];
F_length = new float[S_total];
F_current = new float[S_total];
for(unsigned int index = 0; index < S_total; ++index)
{
FRAME[index] = NULL;
F_total[index] = 0;
F_length[index] = 0.f;
F_current[index] = 0.f;
}
//loop for each array slot and set values of data
return true;
}
void s_group::Release()
{
SDL_FreeSurface(image);
image = NULL;
for(unsigned int s = 0; s < S_total; ++s)
{
for(unsigned int f = 0; f < F_total[s]; ++f)
{
if (FRAME[s])
{
FRAME[s][f].x = 0;
FRAME[s][f].y = 0;
FRAME[s][f].w = 0;
FRAME[s][f].h = 0;
}
}
delete[] FRAME[s];
FRAME[s] = NULL;
}
delete[] FRAME;
FRAME = NULL;
delete[] F_total;
F_total = NULL;
delete[] F_length;
F_length = NULL;
delete[] F_current;
F_current = NULL;
S_total = 0;
S_current = 0;
}
s_group::~s_group(void)
{
Release();
}
should do it.. Just don't forget to allocate memory for FRAME[index] I wasn't sure how much or what you wanted to allocate so I changed the Release function to check if FRAME[index] is valid with an if-statement
I would strongly advise that you use some SmartPointers and forget about handling every single memory allocation yourself..
Since posting this question I have located the source of the error and solved the issue.
In a separate section of code which set the data values for the dynamic 2D array the loop validation was incorrect.
for( unsigned int index = 0; index <= F_total[ S_current ]; ++index ) {
//set data values for each slot in the array
F[ S_current ][ index ].x = 0; etc...
}
As can be seen the loop will clearly attempt to modify a location equal to the size of the created array. Noting of course that arrays begin at index 0, so the final slot will be at size - 1. Something very silly that I missed when writing the code. Actual loop:
for( unsigned int index = 0; index < F_total[ S_current ]; ++index ) {
//set data values for each slot in the array
F[ S_current ][ index ].x = 0; etc...
}
A message for anyone attempting their own memory management:
Finding the source of heap corruption is difficult as the compiler will locate the error in sections of code which do not necessarily cause the problem.
The cause of the problem will only ever be in the section of your code which is affecting the memory. Ensure that you do not attempt to access or worse modify any memory that you have not been given.
I still believe that memory management is a great way to learn and would rather complete any projects in this way than using containers or smart pointers as recommended. This is my personal preference despite custom memory management often offering very few advantages, only complexities.
When asking for assistance provide all related code on the problem. Although the compiler may direct you to the problem in one section, as I said before, with heap corruption it's not necessarily there.

Recursion to add struct in linked list c++

I'm having trouble inserting a struct into a linked list in numerical order. Each struct has a "number" as indicated in the code below. I'm trying to have the struct with the lowest number be the head of the list (ie: be the struct pointed to by "people"). I've been staring at this code on and off all day and I can't figure out what's wrong with it. Any help is much appreciated. Thanks
Person *addPerson(Person *people, Person *addition, int &numList)
{
if (people == NULL && numList == 0)
{
people = addition;
numList++;
return people;
}
if (people->number >= addition->number)
{
addition->nextPerson = people;
people = addition;
return people;
}
else if (people->number < addition->number && people->nextPerson != NULL)
{
addPerson(people->nextPerson, addition, numList);
}
else if (people->number < addition->number && people->nextPerson == NULL)
{
people->nextPerson = addition;
numList++;
return people;
}
}
EDIT**
int main()
{
Person *blake = new Person;
Person *kyra = new Person;
Person *elon = new Person;
Person *bill = new Person;
Person *people = NULL;
blake->number = 1;
blake->name = "blake";
blake->lastName = "madden";
blake->nextPerson = NULL;
kyra->number = 2;
kyra->name = "kyra";
kyra->lastName = "madden";
kyra->nextPerson = NULL;
elon->number = 3;
elon->name = "elon";
elon->lastName = "musk";
elon->nextPerson = NULL;
bill->number = 4;
bill->name = "bill";
bill->lastName = "gates";
bill->nextPerson = NULL;
int num = 0;
int &numList = num;
people = addPerson(people, blake, numList);
people = addPerson(people, kyra, numList);
people = addPerson(people, elon, numList);
people = addPerson(people, bill, numList);
cout << people->name << '\n' << people->lastName;
}
You are not using the return value from addPerson() in the third if block. Try:
people->nextPerson = addPerson(people->nextPerson, addition, numList);
return people;
You also need the return people; in there otherwise you'll run off the end of your function and not return anything sensible (my compiler warned me about that, you should change your warning settings so yours does too).
With the above change, your code appears to run correctly.
You aren't ever assigning the returned head. It should be
people->nextPerson = addPerson(people->nextPerson, addition, numList);
You're problem is the arguments to the function. You're desiring to modify the pointer in the node in the previous caller in the recursive call-order, but you are simply passing the pointer value of the next node. That doesn't allow you to actually modify the pointer-member of the previous node.
Change your function so that it looks like this:
void addPerson(Person** people, Person *addition, int &numList)
Then when you call addPerson in the third block, do it like so:
addPerson(&(*(people)->nextPerson), addition, numList);
And finally when you access the people argument, make sure to-do an extra dereference, for instance:
*people = addition;
or
if ((*people)->number >= addition->number)