Passing linked list from array by reference - c++

My problem is that when trying to add to linked lists within an array it would seem to not work and I'm almost totally ignorant as to why this is. First I declare the object move as seen below:
struct move {
move(int startX, int startY, int endX, int endY)
{
this->startX = startX;
this->startY = startY;
this->endX = endX;
this->endY = endY;
this->next = nullptr;
}
move()
{
next = nullptr;
this->startX = -1;
}
int startX;
int startY;
int endX;
int endY;
move* next;
};
I then declare 2 arrays, one which contains 100 linked lists of the moveobject and another which contains pointers to elements in each of the linked lists in the first array. As seen below:
move possibleMoves[100];
move * endOfLists[100];
I then initialise these arrays as seen below:
for (int i = 0; i < 100; i++) {
possibleMoves[i] = move();
endOfLists[i] = &possibleMoves[i];
}
Moving onto the function itself which adds to one of the linked lists within the possibleMoves array I prototype it as such:
void listAdd(move * list, move * object, int width);
I call it as such:
if (possibleMoves[0].startX == -1) {
possibleMoves[0] = *(new move(x, y, x + xOffset, y + yOffset));
}else {
listAdd(endOfLists[width], new move(x, y, x + xOffset, y + yOffset), width);
}
And the function is declared as such:
void listAdd(move * list, move * object, int width) {
int count = 0;
while (list->next != nullptr){
count++;
list = (*list).next;
}
std::cout << "\nCount: " << count << std::endl;
list->next = object;
endOfLists[width] = list->next;
}
Count always outputs as '0'.
Here is a link to all the code (https://pastebin.com/E5g58N6L) it's not pretty. The listAdd procedure is called on lines 188, 197 and 444. Here is the MCVE:
#include<stdio.h>
#include <stdlib.h>
#include<math.h>
#include<iostream>
struct move {
move(int startX, int startY, int endX, int endY)
{
this->startX = startX;
this->startY = startY;
this->endX = endX;
this->endY = endY;
this->next = nullptr;
}
move()
{
next = nullptr;
this->startX = -1;
}
int startX;
int startY;
int endX;
int endY;
move* next;
};
void listAdd(move * list, move * object, int width);
move possibleMoves[100];
move * endOfLists[100];
int main() {
int x = 0;
int y = 0;
int xOffset = 1;
int yOffset = 1;
int width = 0;
for (int i = 0; i < 100; i++) {
possibleMoves[i] = move();
endOfLists[i] = &possibleMoves[i];
}
if (possibleMoves[0].startX == -1) {
possibleMoves[0] = *(new move(x, y, x + xOffset, y + yOffset));
}else {
listAdd(endOfLists[width], new move(x, y, x + xOffset, y + yOffset), width);
}
void listAdd(move * list, move * object, int width) {
int count = 0;
while (list->next != nullptr)
{
count++;
list = (*list).next; //Go down the list until it reaches an item with nothing next.
}
std::cout << "\nCount: " << count << std::endl;
list->next = object;
endOfLists[width] = list->next;
}

NM the full code. You don't tell us what the initial width is, but assuming it's valid (that is -1<width<100), it doesn't matter. Look at what happens here (end of add function):
list->next = object;
At this point list is endOfLists[width]. Now, you properly set the next to the new object, so far so good.
But what now?
endOfLists[width] = list->next;
So the "head" pointer, saved in the global (why?) is bypassing what it originally pointed to (who has a proper next!) and points directly to a descendant, the new object with NULL next. I'm guessing this wasn't what you want:
Leaking memory 0 - at first static allocation, but this can quickly be dynamic if you call this function the way you did a lot.
The head pointer is still, at the end of the function, an object with NULL next. A new one indeed, but the next is still NULL - so the next call will perform the same actions.
Basically you're swapping the head pointers, while leaking memories. You want to either:
Set the object next first: object->next=endOfLists[width], and set the second line to let endOfLists[width]=object, kind of reversing the list.
Delete the second line, and leave the original head.
Also:
I can't see a good reason for globals
Why is the add function not a move method?
You need to make sure you delete all those new objects.
EDIT
I saw your addition - the first call will always return 0, since all initial objects have NULL nexts, even if you fix your code. You need two calls to the same index (width) at least twice to start testing this.
Graphical addendum
At the beginning we have 100 objects, stored in an array, all looking like this:
head->list->NULL
list here is the object pointed to by endOfLists at some index, and we call that pointer head. Now, we want to add the new object. We enter the addition function, with the first argument endOfLists[width], so this will be our list argument in the function itself.
We immediately skip the while (since our next is already NULL). Getting to the first line above, we now connect our head to the new object:
list->object->NULL
So in the array we have:
head->list->object->NULL
Again, head is the pointer stored in endOfLists[width]. Now we tell endOfLists[width] to swap the head to a different one, setting it equal to list->next, which is object. So how does our memory look like?
head->object->NULL
list->^
Both head (the array cell) and list point to object, and nothing points to list. There we go leaking. Next time we call the function with the updated cell, we will repeat the process, leaking object:
head-> object2->NULL
list->object->^
and so forth.

Related

How can I fix this? " HEAP CORRUPTION DETECTED after normal block.. CRT detected that the application wrote to memory after end of heap buffer "

I had a program working good (without prompting errors) using references, but I decided to use a pointer-to-pointer array allocated on virtual memory, because I can use a variable as the size of the array.
The error prompts when I break the while (m_Window.isOpen()) loop, in other words when I close the game window and the game is finished. I have noticed that the program breaks when I try to erase the virtual memory in the Engine::cleanVirtualMemory() function. I have noticed that it is there because I have put two flags (cout << "running1" << endl; and cout << "running2" << endl) and I can show just the first flag.
Then it prompts a window with the following message:
HEAP CORRUPTION DETECTED after normal block.. CRT detected that the application wrote to memory after end of heap buffer
main.cpp
#include "Engine.h"
using namespace sf;
int main(){
Engine Motor;
Motor.run();
Motor.cleanVirtualMemory();
}
Engine.h
#pragma once
#include <SFML/Graphics.hpp>
#include "StructureBuilder.h"
using namespace sf;
using namespace std;
class Engine{
private:
// Lots of variables ....
Vector2i m_ArenaSize;
Vector2f * vectorStructureArray = new Vector2f[m_ArenaSize.y * m_ArenaSize.x * 4];
int** logicStructureArray = new int*[m_ArenaSize.y];
// Lots of variables ....
//Gameloop
void Input();
void Update(dtAsSeconds);
void Draw();
public:
Engine();
void run();
void cleanVirtualMemory();
};
Engine.cpp
#include "Engine.h"
#include <iostream>
using namespace sf;
Engine::Engine() {
/// lots of variables and data ...
/// Making arena
m_ArenaSize = Vector2i(10, 10);
StructureBuilder(arenaStructures, vectorStructureArray, logicStructureArray, m_ArenaSize);
}
void Engine::run() {
//Timing
Clock clock;
while (m_Window.isOpen()) {
// Each time clock restarted, dt = time elapse (from 0 to now, then clock = 0)
Time dt = clock.restart();
// Convert time elapse to seconds
double dtAsSeconds = dt.asSeconds();
// Call each part of the game in turn
Input();
Update(dtAsSeconds);
Draw();
}
}
void Engine::cleanVirtualMemory() {
// Deallocate Virtual Memory
// first flag
cout << "running1" << endl;
for (int i = m_ArenaSize.x - 1; i > -1; i--) {
delete[] logicStructureArray[i];
}
delete[] logicStructureArray;
logicStructureArray = NULL;
delete[] vectorStructureArray;
vectorStructureArray = NULL;
// second flag
cout << "running2" << endl;
}
StructureBuilder.h
#pragma once
#include <SFML/Graphics.hpp>
#include <iostream>
#include <string.h>
using namespace sf;
using namespace std;
Vector2i StructureBuilder(VertexArray& rVA, Vector2f* rA, int** rLA, Vector2i ArenaSize);
In the following code, you can see where I use pointers, I have erased code just to simplify.
StructureBuilder.cpp
#include "StructureBuilder.h"
Vector2i StructureBuilder(VertexArray& rVA, Vector2f* rA, int** rLA, Vector2i ArenaSize) {
//Set map properties and VertexArrayType
double tileSize = 100;
double Height = ArenaSize.y * tileSize;
double angle = 30;
int offset = 0;
int Primitive = 4;
int currentVertex = 0;
rVA.setPrimitiveType(Quads);
rVA.resize(ArenaSize.x * ArenaSize.y * 4);
// First build graphically our map structures's using char strings
string stringArray[10];
stringArray[0] = "1000000000";
stringArray[1] = "0000000000";
stringArray[2] = "0000010000";
stringArray[3] = "0000000000";
stringArray[4] = "0000000000";
stringArray[5] = "0000000000";
stringArray[6] = "0000000000";
stringArray[7] = "0000000000";
stringArray[8] = "0000000000";
stringArray[9] = "0000000000";
// Convert stringArray to charArray, finally charArray to intArray
char** charArray = new char*[ArenaSize.y];
Vector2f Vector1;
Vector2f Vector2;
Vector2f Vector3;
Vector2f Vector4;
for (int i = 0; i < ArenaSize.x; i++) {
charArray[i] = new char[ArenaSize.x];
rLA[i] = new int[ArenaSize.x];
}
for (int i = 0; i < ArenaSize.x; i++) {
for (int j = 0; j < ArenaSize.y; j++) {
charArray[j][i] = stringArray[j][i];
rLA[j][i] = charArray[j][i] - 48;
// Check when we have a value greater or equal to 1, if yes build a structure.
if (rLA[j][i] == 1) {
Vector1 = Vector2f(Value..., Value...);// in order to understand I dont put the whole calculation here
Vector2 = Vector2f(Value..., Value ...); // is just trigonometry to find vertex
Vector3 = Vector2f(Value..., Value ...);
Vector4 = Vector2f(Value..., Value ...);
rVA[currentVertex + 0].position = Vector1;
rVA[currentVertex + 1].position = Vector2;
rVA[currentVertex + 2].position = Vector3;
rVA[currentVertex + 3].position = Vector4;
rVA[currentVertex + 0].texCoords = Vector2f(42, 0); // coords on my spritesheet
rVA[currentVertex + 1].texCoords = Vector2f(86, 24);
rVA[currentVertex + 2].texCoords = Vector2f(42, 49);
rVA[currentVertex + 3].texCoords = Vector2f(0, 24);
rA[currentVertex + 0] = Vector1; //Later I use this to tell the program where to construct restrictions (where the player can't move)
rA[currentVertex + 1] = Vector2;
rA[currentVertex + 2] = Vector3;
rA[currentVertex + 3] = Vector4;
}
currentVertex = currentVertex + Primitive;
}
}
// Deallocate Virtual Memory
for (int i = ArenaSize.x - 1; i > -1; i--) {
delete[] charArray[i];
}
delete[] charArray;
charArray = NULL;
return ArenaSize;
}
Let's take a look at the declaration of the Engine class.
class Engine{
private:
// Lots of variables ....
Vector2i m_ArenaSize;
Vector2f * vectorStructureArray = new Vector2f[m_ArenaSize.y * m_ArenaSize.x * 4];
The first member of your Engine class is called m_ArenaSize. This is the first class member that will get constructed when an Engine gets constructed. That's how object construction works in C++: when a new object gets constructed, all of the new object's members get constructed in declaration order.
The second member of your Engine class is this vectorStructureArray pointer. It will be allocated to point to an array, with dynamic size, that gets newed using two of the constructed m_ArenaSize's own members, x and y.
And now, let's take a look at Engine's constructor:
Engine::Engine() {
All right. That's your constructor. So, according to our plan, m_ArenaSize is going to get default-constructed since it is not explicitly constructed, in Engine's constructor's initialization section (there is none, here). If you investigate what m_ArenaSize's default constructor does you will discover that it defaults x and y to 0.
And that's what's going to construct the vectorStructureArray pointer, as the 2nd order of business of Engine's default initialization. And, because its x and y are 0, the pointer will point to a grand total of 0 values.
m_ArenaSize = Vector2i(10, 10);
And only now the default-constructed m_ArenaSize gets replaced with a different subject, with different x and y values. The shown code clearly expects the pointer to get reallocated, to reflect m_ArenaSize's new x and y values,. However C++ does not work this way. vectorStructureArray has already been constructed. It's not going to get constructed again simply because a different class member gets replaced. Subsequent code's assumption is the new x and y values, and this results in fairly obvious memory corruption.
The same exact bug occurs with logicStructureArray, too.
These are just the first two major bugs in the shown code regarding memory allocation. There are several ways to fix them, but the easiest way to fix bugs is to make it logically impossible for them to happen in the first place. It is logically impossible for new and delete-related bugs to occur if they are never used. Modern C++ code rarely uses new and delete, but rather employs the services of the C++ library's many containers.
Here, both pointers can be simply replaced by std::vector, with its resize() member taking care of allocating both vectors' sizes. And, as extra bonus, all allocated memory gets automatically freed, automatically preventing all memory leaks.
Replacing all the error-prone new and delete logic with std::vector will fix all memory-related issues in the shown code, the only thing you will have to make sure is that the vectors are correctly resize()d.

Trying to find two random nodes and swap them in a doubly linked list

This program is basically just suppose to shuffle a deck of cards. The cards are stored in a doubly linked list, so 52 nodes. I'm getting a read access error in the getNode function, but I'm pretty sure my loop is correct, so I think the error is stemming from somewhere else. Maybe the swap function. My first step is getting pointers to the nodes that I'm trying to swap.
So I made a function, and I'm pretty sure it's right, except I'm wondering if I should be returning *traverseP instead of just traverseP. I don't think so, because I want to return a pointer to the node, not the value inside the node.
template<class T>
typename ReorderableList<T>::Node *ReorderableList<T>::getNode(int i) const
{
int count = 0;
for (Node *traverseP = firstP; traverseP != NULL; traverseP = traverseP->nextP) {
if (count == i)
return traverseP;
count++;
}
return NULL;
}
Next I made a swap function that take two ints, they represent the values I'm passing into the getNode function
template<class T>
void ReorderableList<T>::swap(int i, int j)
{
// Get pointers to ith and jth nodes.
Node *iPtr = getNode(i);
Node *jPtr = getNode(j);
//create temp Node and store the pointers
Node *temp = new Node;
temp = iPtr->prevP;
temp = iPtr->nextP;
//adjust the iPtr next/prev pointers
iPtr->prevP = jPtr->prevP;
iPtr->nextP = jPtr->nextP;
//adjust the jPtr next/prev pointers
jPtr->prevP = temp->prevP;
jPtr->nextP = temp->prevP;
//I'm a little unclear on these lines. I think they're checking if
//iPtr and jPtr have null pointers. I've tried making them equal jPtr and
//iPtr and that strangly didn't make any difference.
if (iPtr->prevP)
iPtr->prevP->nextP = jPtr;
if (iPtr->nextP)
iPtr->nextP->prevP = jPtr;
if (jPtr->prevP)
jPtr->prevP->nextP = iPtr;
if (jPtr->nextP)
jPtr->nextP->prevP = iPtr;
delete temp;
}
This is the shuffle function where this whole shabang kicks off
template<class T>
void randomShuffle(ReorderableList<T> &list, int n)
{
int randNum = 0;
for (int i = n-1; i > 0; i--)
{
randNum = (rand() & (i + 1));
if (randNum > i)
std::swap(randNum, i);
list.swap(randNum, i);
}
}
I've checked a couple different resources for the swap function and found two that both claimed they were correct, but they looked different to me.
Resource 1
Resource 2

Knights tour passing arrays to linked list and more

I am currently working on the knights tour project. My goal ultimately is to create this project using backtracking (by implementing stack) and Warnsdorff's heuristic. I am not allowed to use any libraries that has stack functions already created such as push and pop. I am also not allowed to resolve the problem using recursion. With that being said, I am pretty stuck right now and my next big milestone would be to solve the problem by only backtracking.
I am not going to sugar coat this at all, but right now my code is one big mess. I have pretty much created all the tools I need to make the program run, but now I just need to put all the pieces together.
The following is my code:
#include<iostream>
using namespace std;
class linkedList{
struct node
{
int data;
node *next;
};
node *top;
public:
linkedList()
{
top = NULL;
}
void push(int coordinates)
{
node *p = new node;
p -> data = coordinates;
p -> next = top;
top = p;
}
int pop()
{
node *temp = top;
top = temp -> next;
return temp -> data;
}
int display()
{
cout<<"\n"<< top -> data;
top = top-> next;
}
};
// Linked List ================================================
class Board{
public:
int next;
int status[8][8];
Board();
void print();
};
Board::Board(){
for(int i=0; i<8; i++){
for(int j=0; j<8; j++){
status[i][j] = -1;
}
}
}//constructor
void Board::print(){
for (int j=0; j<8; j++){
for(int i=0; i<8;i++){
cout << status[i][j] << " ";
}
cout << endl << endl;
}
}
//BOARD========================================================
class Knight {
private:
public:
int vertical[8] = {2,-2,1,-1,2,-2,1,-1}; // possible knight moves x coordinate
int horizontal[8] = {1,1,2,2,-1,-1,-2,-2}; // possible knight move y coordinate
int counter;
int currentPos[2];
Knight();
};
Knight::Knight(){
currentPos[0] = 7; // x-coordiante
currentPos[1] = 7; // y-coordinate
counter = 0;
}//constructor
/* Use this later
int Knight::changePos(int i,int j){
Knight::currentPos[0] = (Knight::currentPos[0] + i);
Knight::currentPos[1] = (Knight::currentPos[1] + j);
counter++;
return counter;
*/
int main(){
Board b;
Knight k;
b.status[k.currentPos[0]][k.currentPos[1]] = k.counter;
b.print();
linkedList obj;
int coordinates;
}
So my idea at this point is to do the following:
Create a loop that will change the current position of the knight using the horizontal and vertical array (the possible moves of the knight). Once the position has changed, the counter will increment and the -1 will be replaced with the current counter value. When the knight has been moved, the information of the new coordinates needs to be passed to the linked list using the push function I created. In order to do this, I need to figure out a way to pass an array (x,y) or multiple values to push. I will also need to create some bound checking which I am currently working on (make sure the knight doesn't move to a spot that he has been to and doesn't go off the board). Then finally if the knight does get stuck, I need to use the pop function I created to go back a step and try to continue with a different move.
I really really appreciate any help, corrections, places to start or other suggestions that are given! I am so stuck..
Let me get this straight. You're having difficulty implementing the Stack structure that allows you to undo moves.
C++ isn't really my forte but here's how I'd approach the Stack
Define a struct that stores the coords (and possibly backtracking info)
Update 'node' to store a pointer to an instance of your new struct.
Update the 'push()' definition to use it.
Update the 'pop()' definition to return it.
Profit...

Array of Linked Lists C++

So I thought I understood how to implement an array of pointers but my compiler says otherwise =(. Any help would be appreciated, I feel like I'm close but am missing something crucial.
1.) I have a struct called node declared:.
struct node {
int num;
node *next;
}
2.) I've declared a pointer to an array of pointers like so:
node **arrayOfPointers;
3.) I've then dynamically created the array of pointers by doing this:
arrayOfPointers = new node*[arraySize];
My understanding is at this point, arrayOfPointers is now pointing to an array of x node type, with x being = to arraySize.
4.) But when I want to access the fifth element in arrayOfPointers to check if its next pointer is null, I'm getting a segmentation fault error. Using this:
if (arrayOfPointers[5]->next == NULL)
{
cout << "I'm null" << endl;
}
Does anyone know why this is happening? I was able to assign a value to num by doing: arrayOfPointers[5]->num = 77;
But I'm confused as to why checking the pointer in the struct is causing an error. Also, while we're at it, what would be the proper protoype for passing in arrayOfPointers into a function? Is it still (node **arrayOfPointers) or is it some other thing like (node * &arrayOfPointers)?
Thanks in advance for any tips or pointers (haha) you may have!
Full code (Updated):
/*
* Functions related to separate chain hashing
*/
struct chainNode
{
int value;
chainNode *next;
};
chainNode* CreateNewChainNode (int keyValue)
{
chainNode *newNode;
newNode = new (nothrow) chainNode;
newNode->value = keyValue;
newNode->next = NULL;
return newNode;
}
void InitDynamicArrayList (int tableSize, chainNode **chainListArray)
{
// create dynamic array of pointers
chainListArray = new (nothrow) chainNode*[tableSize];
// allocate each pointer in array
for (int i=0; i < tableSize; i++)
{
chainListArray[i]= CreateNewChainNode(0);
}
return;
}
bool SeparateChainInsert (int keyValue, int hashAddress, chainNode **chainListArray)
{
bool isInserted = false;
chainNode *newNode;
newNode = CreateNewChainNode(keyValue); // create new node
// if memory allocation did not fail, insert new node into hash table
if (newNode != NULL)
{
//if array cell at hash address is empty
if (chainListArray[hashAddress]->next == NULL)
{
// insert new node to front of list, keeping next pointer still set to NULL
chainListArray[hashAddress]->next = newNode;
}
else //else cell is pointing to a list of nodes already
{
// new node's next pointer will point to former front of linked list
newNode->next = chainListArray[hashAddress]->next;
// insert new node to front of list
chainListArray[hashAddress]->next = newNode;
}
isInserted = true;
cout << keyValue << " inserted into chainListArray at index " << hashAddress << endl;
}
return isInserted;
}
/*
* Functions to fill array with random numbers for hashing
*/
void FillNumArray (int randomArray[])
{
int i = 0; // counter for for loop
int randomNum = 0; // randomly generated number
for (i = 0; i < ARRAY_SIZE; i++) // do this for entire array
{
randomNum = GenerateRandomNum(); // get a random number
while(!IsUniqueNum(randomNum, randomArray)) // loops until random number is unique
{
randomNum = GenerateRandomNum();
}
randomArray[i] = randomNum; // insert random number into array
}
return;
}
int GenerateRandomNum ()
{
int num = 0; // randomly generated number
// generate random number between start and end ranges
num = (rand() % END_RANGE) + START_RANGE;
return num;
}
bool IsUniqueNum (int num, int randomArray[])
{
bool isUnique = true; // indicates if number is unique and NOT in array
int index = 0; // array index
//loop until end of array or a zero is found
//(since array elements were initialized to zero)
while ((index < ARRAY_SIZE) && (!randomArray[index] == 0))
{
// if a value in the array matches the num passed in, num is not unique
if (randomArray[index] == num)
{
isUnique = false;
}
index++; // increment index counter
} // end while
return isUnique;
}
/*
*main
*/
int main (int argc, char* argv[])
{
int randomNums[ARRAY_SIZE] = {0}; // initialize array elements to 0
int hashTableSize = 0; // size of hash table to use
chainNode **chainListArray;
bool chainEntry = true; //testing chain hashing
//initialize random seed
srand((unsigned)time(NULL));
FillNumArray(randomNums); // fill randomNums array with random numbers
//test print array
for(int i = 0; i < ARRAY_SIZE; i++)
{
cout << randomNums[i] << endl;
}
//test chain hashing insert
hashTableSize = 19;
int hashAddress = 0;
InitDynamicArrayList(hashTableSize, chainListArray);
//try to hash into hash table
for (int i = 0; i < ARRAY_SIZE; i++)
{
hashAddress = randomNums[i] % hashTableSize;
chainEntry = SeparateChainInsert(randomNums[i], hashAddress, chainListArray);
}
system("pause");
return 0;
}
arrayOfPointers = new node*[arraySize];
That returns a bunch of unallocated pointers. Your top level array is fine, but its elements are still uninitialized pointers, so when you do this:
->next
You invoke undefined behavior. You're dereferencing an uninitialized pointer.
You allocated the array properly, now you need to allocate each pointer, i.e.,
for(int i = 0; i < arraySize; ++i) {
arrayOfPointers[i] = new node;
}
As an aside, I realize that you're learning, but you should realize that you're essentially writing C here. In C++ you have a myriad of wonderful data structures that will handle memory allocation (and, more importantly, deallocation) for you.
Your code is good, but it's about how you declared your InitDynamicArrayList. One way is to use ***chainListArray, or the more C++-like syntax to use references like this:
void InitDynamicArrayList (int tableSize, chainNode **&chainListArray)

Why am I leaking memory here (depth first search) c++?

int Solver::negamax(Position* pos,int alpha,int beta, int color, int depth ) {
if(depth==0 || is_final(pos)){
return evaluate(pos);
}
else{
vector < Position* > moves = generate_moves(pos->get_board());
vector < Position* >::iterator move;
int min = 99999;
for(move = moves.begin(); move < moves.end(); move++){
int val = negamax(*move,alpha, beta, -color, depth - 1 );
if(val <= min){
min = val;
delete best;
best = NULL;
best = (*move)->get_board();
}
else{
delete *move; //So this isnt cleaning up?
*move = NULL;
}
}
min = -min;
return min;
}
}
vector < Position* > TakeAwaySolver::generate_moves(Board *brd){
TakeAwayBoard *board = static_cast<TakeAwayBoard*>(brd);
vector < Position* > moves;
if(board->get_data() >= 3){
TakeAwayBoard *b = new TakeAwayBoard(board->get_data() - 3);
Position* p = new Position(b);
moves.push_back(p);
}
if(board->get_data() >= 2){
TakeAwayBoard *b = new TakeAwayBoard(board->get_data() - 2);
Position* p = new Position(b);
moves.push_back(p);
}
TakeAwayBoard *b = new TakeAwayBoard(board->get_data() - 1);
Position* p = new Position(b);
moves.push_back(p);
return moves;
}
I valgrinded my program and I'm apparently leaking memory. It seems that I'm deleting all unused objects, but perhaps I'm not understanding something. generate_moves() does allocate memory for each of the objects being pushed in. Evaluate returns 1. Does it seem possible that I'm leaking memory in any location?
You have an if/else in which *move is only deleted in one of the paths. I'd check there.
for(move = moves.begin(); move < moves.end(); move++){
int val = negamax(*move,alpha, beta, -color, depth - 1 );
if(val <= min){
min = val;
delete best;
best = NULL;
best = (*move)->get_board();
//best is deleted, but *move is not
}
else{
delete *move;
*move = NULL;
}
}
A std::vector<position *> container will not automatically delete the inserted elements when it is destroyed. Make it a std::vector<x<position *> > where x is some suitable smart pointer template, like auto_ptr.
If you don't want to do that, then the next best thing is to wrap the vector in a class whose destructor iterates over the vector and calls delete on every pointer.
I.e. this is a memory leak:
{
std::vector<int *> vec;
vec.push_back(new int[3]);
// vec goes out of scope
}
Sure, the vector cleans itself up! It deletes its internal array, etc. But it does nothing with the new int[3] that we allocated and put into the vector.
It seems to me that you never clear the 'minimum' positions.
You store a pointer to the board in best, and take care to clear that when you replace it with a better minimum, and in case the move isn't a minimum so far, you properly clean it up, but you never clean the actual position pointer in case it's a minimum.
As a side note, this is redundant:
best = NULL;
best = (*move)->get_board();