Ive problem with my code (C++)causing memory leak ( i belive). Basically i want it to do the following: take data from user untill he writes "stop" and make heap out of that data. I guess that I'm missing a removal of booked memory at some point but i dont know how to fix it. Also the code seems to be working in code::blocks but it crashes in Dev C++.
cout<<"Enter data to heap if u wanna stop write stop."<<endl;
int *w1=new int[1];
int kek=0;
while(true)
{
cin>>*(w1);
if (!cin)
{ /// the "stop"" thingy
w1=w1-kek;
cout<<"heap: "<<endl;
for (int i=0;i<kek;i++)
{
cout<<" "<<*w1<<" ";
w1++;
}
break;
}
int *w2=new int[2+kek];
w1=w1-kek;
for(int t=0;t<kek+1;t++) ///rewriting data to new chunks of memory
{
*w2=*w1;
w2++;
w1++;
}
delete[]w1; ///releasing old ones ( i think something is wrong here)
w1=w2;
kek++;
w1=w1-kek-1;
int kekkeeper=kek;
for(int l=log(kek)/log(2);l>0;l--) /// heapnig things up
{
if(*(w1+kekkeeper/2)>*(w1+kekkeeper)) swap (*(w1+kekkeeper/2),*(w1+kekkeeper));
else break;
kekkeeper=kekkeeper/2;
}
w1=w1+kek+1;
w2=NULL;
delete[]w2;
}
look at the last tow lines
you set w2 to NULL before your delete it
you changed both pointers w1 and w2 in the following loop
for(int t=0;t<kek+1;t++) {
*w2=*w1;
w2++;
w1++;
}
so you must reset this modification for each pointer before deleting it.
the reseting instruction for w1 can look like this
w1=w1-(kek+1);
delete[]w1;
and for w2 like this
w2=w2-kek;
delete[]w2;
finally you must move the allocation of w1 into the while loop.
Related
This is from a homework assignment that was already turned in. The program is a card game that plays correctly but seg faults when the game is over. I can trace the core dump to my delete [] playerArr, but I think the real problem is in how I'm declaring my playerArr.
I have a constructor, copy, overloaded operator and destructor in my .h file that works well with other programs so I think my problem is in main. I've looked at several other questions here and on google and haven't found one quite like this. Here are the code snippets:
struct Player
{
int currentHand; //current number of cards in given player's hand
Queue hand; //queue to store player's hand
};
in main I allocate an array of structs, I think this is my problem. I've trial and errored a variety of approaches but this one allows my program to compile and my game to play as designed:
//allocate array of Player structs
Player *playerArr = new Player[numPlayers];
for (int i = 1; i <= numPlayers; i++)
playerArr[i].currentHand = 0;
//enqueue playerArr.hand
deal(playerArr, deck, numPlayers, currentDeck);
this is the sequence I use to clean up before deleting, the core dumps after cout:
//exit do-while loop and end game
}
while (playerArr[currentPlayer - 1].currentHand != 0);
for (int i = 1; i < numPlayers; i++)
{
while (playerArr[i].currentHand > 0)
{
playerArr[i].hand.dequeue(catchQ);
playerArr[i].currentHand--;
}
}
//empty all deck/discard stacks
while (!deck.isEmpty())
deck.pop(catchPop);
while (!discard.isEmpty())
discard.pop(catchPop);
//reset hand/deck counters to defaults
catchQ = 0;
catchPop = 0;
currentDeck = 52;
currentPlayer = 1;
numPlayers = 2;
cout << "\n\n\n\t Good Game!" << endl << endl;
//free dynamic memory
delete [] playerArr;
It's too late for me to change my grade on this program and with finals week I don't have time to visit my prof during office hours so if someone has a solution for me I can learn from this mistake and move on.
Thank you
One probable cause of the problem is that you forget that array-indexes are zero-based.
An array of numPlayers elements will have indexes from 0 to numPlayers - 1 (inclusive).
The first loop you show doesn't use that, instead if goes from 1 to numPlayers, leading you to index the allocated memory out of bounds which leads to undefined behavior.
My homework is that I have to make a class (register) which contains 3 class arrays (birds, mammals, reptiles) which are in the animal class. Animal is the friend of Register. I will only show the birds part, to keep it simple.
The register class looks like:
class Register
{
Bird* birds;
unsigned int birdSize;
public:
...
}
The constructor of register:
Register::Register()
{
this->birds = new Bird[0];
this->birdSize = NULL;
}
Now I have a function in register that adds one element to the birds array, the input is cin.
void Register::add()
{
...
if (birdSize == 0)
{
birds = new Bird[0];
Bird* temp = new Bird[0];
temp[0].add();
this->birds = temp;
birdSize++;
}
else
{
Bird* temp = new Bird[birdSize+1];
for (unsigned int i=0; i<=birdSize; i++)
{
temp[i] = this->birds[i];
}
temp[birdSize+1].add();
birds = new Bird[birdSize+1];
birds = temp;
birdSize++;
}
temp[0].add() has the cin, it works properly. When I run the program, the user has to add 2 birds to the array. The problem occurs when reaching the part under 'else', so the second element of the array. The program surely reaches "temp[birdSize+1].add();" while running, then the "xyz.exe has stopped working" window pops up and it says in the details " Fault Module Name: StackHash_7e8e" so I'm sure something is wrong with the memory allocation, but the problem is that when I try to find the problematic line in debug mode, everything works fine.
Well, not everything. The program has a print() function, it prints out everything in Register. The second element of the array is the same as the first.
I have no clue what to do. I read many forum posts, read a cpp book, watched online tutorials, but I can't find the solution for this problem. Please help.
Array index starts from 0. So in else part you are writing
Bird* temp = new Bird[birdSize+1]; // size =birdSize +1;
So valid index range will be 0 -> birdSize, not birdSize+1.
The problem is
temp[birdSize+1].add();
you are using birdSize+1th index. It should be
temp[birdSize].add();
There are other bugs in your code:
for (unsigned int i=0; i<=birdSize; i++) // should be i<birdSize
{
temp[i] = this->birds[i];
}
There are other bad coding in your program:
Register::Register()
{
this->birds = new Bird[0]; // should be this->birds=NULL
this->birdSize = NULL; // should be this->birdSize = 0
}
And obviously if your homework does not demand it, you should not use arrays in this way. For variable size container, use vector, list.... Array is only when the size is fixed.
this is my first data structure program. I am implementing a simple stack using array with push, pop and initialize functions. I am getting an infinite loop as the output. Could you please tell me why is this so?
#include<iostream>
using namespace std;
# define SIZE 6
class stack{
public:
void init();
void push(int i);
int pop();
int top;
int stck[SIZE];//bydefault private
};
void stack::init()
{
top=0;
return;
}
void stack::push(int i)
{
if(top==SIZE)
{
cout<<"stack is full";
return;
}
else
{
top=top+1;
stck[top]= i;
return;
}
}
int stack::pop()
{
if(top==0)
{
cout<<"stack is empty. \n";
return 0;
}
else
{
top = top-1;
return(stck[top-1]);
}
}
int main()
{
stack stack1;
stack1.init();
int a;
int m;
while(a!=4)
{
cout<<"1. push 2. pop 3.display 4.exit .\n";
cin>>a;
if(a==1){
cout<< "enter value";
cin>>m;
stack1.push(m);
}
if(a==2)
{
cout<<"popped"<< stack1.pop();
}
if(a==3)
{
for(int k=0; k<=stack1.top;k++)
{
cout<<stack1.stck[k];
}
}
}
}
You never initialize a, so your program has undefined behaviour. Specifically, the while (a != 4) line performs an lvalue-to-rvalue conversion of a while its value is indeterminate, which the C++ standard explicitly states as undefined behaviour in section 4.1.
However, I doubt this is causing the issue at hand. In practice, unless the optimizer just optimized all your code out, your program should usually behave as expected; it's only when a == 4 on the first loop that you have problems. This doesn't make the code acceptable, but there's probably more to it.
I suspect the problem is that you use top to represent one past the number of elements. When you have zero elements, you point to the first; when you have one, you point to the second, etc. This means you're pointing to the first unused element.
However, in both your push and pop functions, you change top first and only then access the stack, but acting as if you didn't change it:
top = top + 1;
stck[top] = i;
When your stack is empty, this will set top to 1 and then access stck[1]. Meanwhile, stck[0] is left unset. When popping, you have the opposite:
top = top - 1;
return stck[top-1];
This sets top back to 0, but returns stck[-1], which is out of bounds.
I suspect that if you push SIZE values onto the stack, you will end up overwriting unrelated memory, which could cause all kinds of trouble. I still don't see how an infinite loop will follow, but given the behaviour is undefined, it is certainly a possible result.
(The alternative is that you at some point enter something other than a number. Seeing as you never check whether your input succeeded, if a != 4 and you enter something invalid, all further reads will fail, and a will remain unequal to 4. You could fix this by making changing your while to be
while (a != 4 && std::cin)
In that case, if you enter something invalid and std::cin goes into a non-good state, your loop (and thus program) will end.)
You only have a single loop, terminated based on user input.
If cin>>a fails, a will have whatever value it started with (undefined in your code), and you will loop on that unchanging value.
Typical ways for the input call to fail include
pressing control+D (on a *nix system)
pressing control+Z (on a Windows system)
redirected input from a pipe or file which is exhausted
There may be other causes of failed input as well.
So this is a reduced version of my main / Initializer function. When I call it and it has to add any items to the players inventor, I get a Debug Assertation Failed error.
It seems to me like I am mixing up the scope somewhat?
Am I declaring something new inside the scope of the function, and then not being able to access it again out in main?
I tried a few things inside the function, like using Getters/Setters instead of assigning is completely, like p_player = p but I don't think that actually deals with the problem at all, and I'm kind of confused.
int main()
{
Array<Item> items(3);
string itemsfilename = "itemsfile.txt";
Initializer::InitializeItems(items, itemsfilename);
Login login;
Player p1;
string filename = login.LoginToGame();
Initializer::InitializePlayer(p1, rooms, items, 3, filename);
}
void Initializer::InitializePlayer(Player& p_player, HashTable<string, Room>& p_rooms, Array<Item>& p_items, int p_numItems, std::string& p_filename)
{
ifstream playerfile(p_filename);
int inventorycount = 0;
//all the stuff needed to make a player
std::string name;
int health;
int confidence;
int humor;
int speed;
std::string room;
Room* currentRoom;
Inventory inventory(100);
//reading in values from file
for(int i = 0; i < inventorycount; i++)
{
playerfile.getline(value, 256);
std::string item(value);
for(int j = 0; j < p_numItems; j++)
{
if(p_items[j].GetName() == item)
{
inventory.AddItem(&(p_items[j])); //This line taken out, removes the error.
}
}
}
Player p(name, health, confidence, humor, speed, currentRoom, inventory);
p_player = p;
}
AddItem() takes a pointer to an item, and then appends it to it's DLinkedList.
Edit:
The error I get is
Debug Assertation Failed!
Program: zzz
File f:\dd/vctools/crt_bld/self_x86/crt/src/dbgdel.cpp
Line: 52
Expression: _Block_TYPE_IS_VALID(pHead->nBlockUse)
AddItem() Code:
bool AddItem(Item* p_item)
{
if(p_item->GetWeight() + m_weight <= m_maxWeight)
{
m_inventory.Append(p_item);
m_weight += p_item->GetWeight();
}
else
{
return false;
}
return true;
}
Ok, so we still don't have the code that actually causes the problem, but I'm pretty certain I know what's going on, and to avoid getting into a "20 questions of add more code" - there's two possible scenarios:
Items is an array of objects, and you store pointers to them in your m_inventory container. When destroying this container, the objects are destroyed by calling delete on the items - which doesn't work since the content is not allocated from the heap.
When you copy the inventory the m_inventory container is not appropriately copied, and the contents fall apart because the pointers to the storage is failing.
If this doesn't help, then please try to reduce your code to something that only shows this problem, without using files that we don't know the content of and can be posted as a complete program in the question with all the code necessary [remove any other code that isn't needed], so we can see EVERYTHING. Currently, we're only seeing a few bits of the code, and the problem is almost certainly DIRECTLY in the code you've shown us.
I'm running CodeBlocks on the MingW compiler in an XP virtual machine. I wrote in some simple code, accessible at cl1p , which answers the algorithm question at CodeChef (Well it only answers it partly, as I have not yet included the loop for multiple test cases.
However, my problem is, that while running it in debug mode, it gives the correct output of 5, for the input:
3
1
2 1
1 2 3
However, when I build and run it, it gives the absurd, huge output 131078, what seems like garbage to me. I do not understand how the hell this is happening, but am guessing it's something to do with the dynamic memory allocation. What's the problem here, and how can I fix it? I even ran it through the online compiler at BotSkool, and it worked fine. After adding the loop for test cases, the code even worked correctly on CodeChef!
#include <iostream>
using namespace std;
int main()
{
// Take In number of rows
int numofrows;
cin >> numofrows;
// Input Only item in first row
int * prevrow;
prevrow = new int[1];
cin >> prevrow[0];
// For every other row
for (int currownum = 1; currownum < numofrows; currownum++)
{
// Declare an array for that row's max values
int * currow;
currow = new int[currownum+1];
int curnum;
cin >> curnum;
// If its the first element, max is prevmax + current input
currow[0] = prevrow[0] + curnum;
// for every element
int i = 1;
for (; i <= currownum; i++)
{
cin >> curnum;
// if its not the first element, check whether prevmax or prev-1max is greater. Add to current input
int max = (prevrow[i] > prevrow[i-1]) ? prevrow[i] : prevrow[i-1];
// save as currmax.
currow[i] = max + curnum;
}
// save entire array in prev
prevrow = new int[i+1];
prevrow = currow;
}
// get highest element of array
int ans = 0;
for (int j=0; j<numofrows; j++)
{
if (prevrow[j] > ans)
{
ans = prevrow[j];
}
}
cout << ans;
}
Run the code through Valgrind on a Linux machine and you'll be amazed at how many places your code is leaking memory.
If you are taking the hard road of managing your memory, do it well and 'delete' all the new-allocated memory before allocating more.
If, on the other hand, you prefer the easy road, use a std::vector and forget about memory management.
For one thing, this:
//save entire array in prev
prevrow = new int [i+1];
prevrow = currow;
copies the pointer, not the whole array.
In your loop, you have this line
int max = (prevrow[i]>prevrow[i-1])?prevrow[i]:prevrow[i-1];
On the first iteration of the main loop, when currownum == 1, the loop containing this line will be entered, as i is initialized to 1. But on the first iteration, prevrow only has one element and this line tries to access prevrow[1]. In a debug build, the memory simply gets initialized to zero, but in a normal build, you get some garbage value that just happened to be in the memory, leading to the result you see.
Pretty much always, when you get garbage values in a normal build, but everything is fine in a debug build, you are accessing some uninitialized memory.
Also, your program is leaking memory like crazy. For instance, you don't need to assign any result of new inside the loop to prevrow because right after that you change prevrow to point to another block of allocated memory. Also, you should call delete for any memory that you are no longer using.