C++ will this function leak? - c++

I have started out to write a simple console Yahtzee game for practice. I just have a question regarding whether or not this function will leak memory. The roll function is called every time the dices need to be re-rolled.
What it does is to create a dynamic array. First time it is used it will store 5 random values. For the next run it will only re-roll all except for the dice you want to keep. I have another function for that, but since it isn't relevant for this question I left it out
Main function
int *kast = NULL; //rolled dice
int *keep_dice = NULL; //which dice to re-roll or keep
kast = roll(kast, keep_dice);
delete[] kast;
and here's the function
int *roll(int *dice, int *keep) {
srand((unsigned)time(0));
int *arr = new int[DICE];
if(!dice)
{
for(int i=0;i<DICE;i++)
{
arr[i] = (rand()%6)+1;
cout << arr[i] << " ";
}
}
else
{
for(int i=0;i<DICE;i++)
{
if(!keep[i])
{
dice[i] = (rand()%6)+1;
cout << "Change ";
}
else
{
keep[i] = 0;
cout << "Keep ";
}
}
cout << endl;
delete[] arr;
arr = NULL;
arr = dice;
}
return arr;
}

Yes, it can leak. Just for example, using cout can throw an exception, and if it does, your delete will never be called.
Instead of allocating a dynamic array yourself, you might want to consider returning an std::vector. Better still, turn your function into a proper algorithm, that takes an iterator (in this case, a back_insert_iterator) and writes its output there.
Edit: Looking at it more carefully, I feel obliged to point out that I really dislike the basic structure of this code completely. You have one function that's really doing two different kinds of things. You also have a pair of arrays that you're depending on addressing in parallel. I'd restructure it into two separate functions, a roll and a re_roll. I'd restructure the data as an array of structs:
struct die_roll {
int value;
bool keep;
die_roll() : value(0), keep(true) {}
};
To do an initial roll, you pass a vector (or array, if you truly insist) of these to the roll function, which fills in initial values. To do a re-roll, you pass the vector to re-roll which re-rolls to get a new value for any die_roll whose keep member has been set to false.

Use a (stack-allocated) std::vector instead of the array, and pass a reference to it to the function. That way, you'll be sure it doesn't leak.

The way you allocate memory is confusing: memory allocated inside the function must be freed by code outside the function.
Why not rewrite it something like this:
int *kast = new int[DICE]; //rolled dice
bool *keep_dice = new bool[DICE]; //which dice to re-roll or keep
for (int i = 0; i < DICE; ++i)
keep_dice[i] = false;
roll(kast, keep_dice);
delete[] kast;
delete[] keep_dice;
This matches your news and deletes up nicely. As to the function: because we set keep_dice all to false, neither argument is ever NULL, and it always modifies dice instead of returning a new array, it simplifies to:
void roll(int *dice, int *keep) {
for(int i=0;i<DICE;i++)
{
if(keep[i])
{
keep[i] = false;
cout << "Keep ";
}
else
{
dice[i] = (rand()%6)+1;
cout << "Change ";
}
}
cout << endl;
}
Also, you should move the srand call to the start of your program. Re-seeding is extremely bad for randomness.

My suggestion would be to take time out to buy/borrow and read Scott Meyers Effective C++ 3rd Edition. You will save yourselves months of pain in ramping up to become a productive C++ programmer. And I speak from personal, bitter experience.

Related

Vector of a class resetting member variables after for loop

I have an assignment where we need to use this basic structure of vectors and classes to learn about parent and child classes and polymorphism. Here is the code of the function I'm supposed to write:
void assignStudents(vector<Student*>& v) {
for (int i = 0; i < 5; i++)
{
cout << "Enter a study level: ";
string input;
cin >> input;
if (input == "graduate")
{
Graduate inputClass;
Student* inputParentClassPtr = &inputClass;
v.push_back(inputParentClassPtr);
v[i]->addToVector(input);
inputParentClassPtr = nullptr;
}
else if (input == "undergraduate")
{
Undergraduate inputClass;
Student* inputParentClassPtr = &inputClass;
inputParentClassPtr->addToVector(input);
v.push_back(inputParentClassPtr);
}
else
{
cout << "Please enter a valid response, either graduate or undergraduate" << endl;
i--;
}
}
for (size_t i = 0; i < v.size(); i++)
{
vector<string> studyLevels = v[i]->getStudyLevels();
size_t size = studyLevels.size();
for (int j = 0; j < size; j++)
{
cout << studyLevels[j];
}
}
}
I debug the program and every time the first for loop moves on to the next iteration, every member variable inside each object in my vector goes blank, but then when I add a new object into the vector, then call the addToVector() function they come back.
I added the bottom for loop to check if any editing is happening, and once I get to that bottom for loop, every member variable is empty again.
I have the Student class vector where I am adding Undergraduate and Graduate classes to. Every Student class has a protected vector inside called levels. I need to add the class to vector that holds all my objects, then edit the member variable vector to include the string representing the type of class it is.
Why do the member variables (levels) go blank every time it finishes an iteration of the for loop?
I'll just focus on one part, as the same issue appears twice in your code.
{
Graduate inputClass; // create local student "on the stack"
Student* inputParentClassPtr = &inputClass;
v.push_back(inputParentClassPtr); // store address of student
v[i]->addToVector(input);
inputParentClassPtr = nullptr; // has no real effect
} // inputClass goes out of scope and is destroyed here
When the block ends, the local "stack" variables from that block are destroyed. That means the Graduate object is no longer valid, and the pointer you stored in v is now pointing at something unusable.
To fix that, you need to create the objects in dynamic memory.
You should change your vector to store std::unique_ptr<Student>, and create the objects using std::make_unique(), like this:
auto inputParentClassPtr = std::make_unique<Graduate>();
v.push_back(std::move(inputParentClassPtr));
But, if you can't do that, you will need to use new instead, like this:
Student* inputParentClassPtr = new Graduate();
v.push_back(inputParentClassPtr);
Either way, even though inputParentClassPtr is still destroyed at the end of the block, it is only a pointer and the Graduate object it pointed to is still alive.
If you use new, you'll then need to delete all the objects in the vector when you are done using them, or you'll have a memory leak. Using std::unique_ptr will handle that for you.

c++ pointer to function and void pointers iteraction resulting in wierd things

Im making a little project at home about genetic algorithm. But im trying to make it generic, so i use pointers to function and void pointers. but i think it might be making some problems.
The main goal of this section of the project is to get a pointer to a function, which return a certain struct. The struct containing a void pointer
and when im trying to view the value of where it points too it isn`t quite right.I suspect that maybe the interaction between these two might be causing me some problems.
details:
struct:
struct dna_s{
int size;
void *dna;
};
population is a class contaning all the population for the process. besides, it contains 2 functions as well, init_func and fitter_func which are both pointers to functions.
pointer to function definition:
typedef dna_s (*init_func_t)();
typedef int (*fitter_func_t)(dna_s);
population class:
class population{
private:
// Parameters
int population_size;
node *pop_nodes;
// Functions
init_func_t init_func;
fitter_func_t fitter_func;
public:
population(int pop_size,init_func_t initialization_func){
// Insert parameters into vars.
this->population_size = pop_size;
this->init_func = initialization_func;
// Create new node array.
this->pop_nodes = new node[this->population_size];
for(int i = 0;i < this->population_size; i++){
dna_s curr_dna = this->init_func();
char *s = static_cast<char*>(curr_dna.dna);
cout << s << endl;
this->pop_nodes[i].update_dna(curr_dna);
}
}
};
You can see that in the constructor im inserting a pointer to function, init_func. this function is generating random words.
init_func:
dna_s init_func(){
string alphanum = "0123456789!##$%^&*ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
char init_s[STRING_SIZE+1] = {};
dna_s dna;
// Generate String
for(int i = 0; i < STRING_SIZE; i++){
init_s[i] = alphanum[rand() % alphanum.size()];
}
cout << "-->" << init_s << endl;
// Insert into struct.
dna.size = STRING_SIZE;
dna.dna = static_cast<void*>(&init_s);
// Return it
return dna;
}
the main function is not so interesting but it might be connected:
int main(){
// Init srand
srand(time(0));
// Parameters
int population_size = 10;
population pop(population_size, init_func);
}
now for the interesting part, whats the problem?
in the init_func the cout prints:
-->e%wfF
which is all good
but in the population class the cout prints:
e%Ω²(
and the wierd thing is the first 2 characters will always be the same, but the other 3 will always be this string Ω²(.
example:
-->XaYN7
XaΩ²(
-->oBK9Q
oBΩ²(
-->lf!KF
lfΩ²(
-->RZqMm
RZΩ²(
-->oNhMC
oNΩ²(
-->EGB6m
EGΩ²(
-->osafQ
osΩ²(
-->3#NQt
3#Ω²(
-->D62l0
D6Ω²(
-->tV#mu
tVΩ²(
Your code has a few lifetime issues. In your dna_S struct:
void *dna;
This is a pointer, it points to an object that exists elsewhere. Then, in your init_func:
dna_s init_func(){
...
char init_s[STRING_SIZE+1] = {};
dna_s dna;
...
dna.dna = static_cast<void*>(&init_s);
...
return dna;
}
init_s is a variable that exists inside init_func, you make dna point to that variable and then leave the function. init_s ceases to exist at this point, dna is pointing nowhere useful when the population constructor gets it, causing undefined behavior.
You could work around that by allocating memory with new char[], like you did for pop_nodes, but you are responsible for deleting that memory when it is no longer used.

How to correctly re-use pointer object to custom class

I have a lot of code so I am going to try to do this with as little as possible to show you guys.
I am writing a program that is leaking memory, my efforts of cleaning up memory is causing my program to crash (only in Visual Studio, not using MinGw). I am using Visual Studio 2015 to debug my code, and see how much memory I am using. However, when adding the delete keyword to try to free up some memory Visual Studio triggers a breakpont. When following the breakpoint to try and figure out whats wrong, VS takes me to a page that says 'No Source Available'.
Compiling this same code with MinGw gcc works find and executes fine, however I need Visual Studio's debugger so I can see my memory usage so that I can determine if the leak is fixed or not.
I am creating a lot of objects dynamically and re assigning new objects to them, I need help figuring out how to delete the old memory so I can only keep in memory the newly created object.
Here is the code that I am concerned with
StateNode *initState = nullptr; // Pointer to the initial state
StateNode *finishState = nullptr; // Pointer to the final state
bool finished = false; // Flag for checking if the puzzle has completed
size = getNumQueens();
// Make dynamic 2D array of the specified size
char** init = new char*[size];
for (int i = 0; i < size; i++)
init[i] = new char[size];
// Puzzle main loop
while (!finished)
{
// Randomize the queens placement on the board
randomizeGame(init, size);
// Make the initial state with the current game board
initState = new StateNode(init, size);
// Run the hillclimbing algo
finishState = HillClimbing<StateNode>::Run(initState, size);
// Check to see if the algo returned a valid end state
if (finishState->getHeuristic() == 0)
finished = true;
else
{
// Try to clean up memory to prevent memory leak
delete initState; // This is where Visual Studio throws breakpoint
delete finishState;
}
}
As you can see, this while loop constantly creates new StateNode objects by assigning them to initState. Also, the HillClimbing::Run() method returns a dynamically created StateNode and assigns it to finishState.
Without this code:
else
{
// Try to clean up memory to prevent memory leak
delete initState; // This is where Visual Studio throws breakpoint
delete finishState;
}
My program leaks a lot of memory, approaching 2GB when the program crashes.
With those lines VS throws breakpoints, but MinGw gcc does not, and the program works a lot faster.
My main question: How can I correctly manage the memory of initState and finishState to fix memory leaks.
i.e. How can I only keep in memory one StateNode object, while deleting all other instances as I go.
EDIT
This is what is in the VS output window
The thread 0x4244 has exited with code 1857355776 (0x6eb50000).
HEAP[N-Queens.exe]: Invalid address specified to RtlValidateHeap( 01230000, 0126B540 )
N-Queens.exe has triggered a breakpoint.
When going into the dissasembly and pressing F11 to keep going through the code, eventually this happens:
EDIT 2
StateNode.h
class StateNode
{
private:
char** state;
int heuristic;
int size;
public:
StateNode(char** state, int size);
int getHeuristic();
void printState();
char** getState();
};
Here is the code for StateNode.cpp
#include <iostream>
#include "state-node.h"
#include "heuristic.h"
/* Constructor, accepts a state and a size (the number of queens) */
StateNode::StateNode(char ** state, int size)
{
this->state = state;
this->size = size;
this ->heuristic = NQueens::CalcHeuristic(state, size);
}
/* Returns the heuristic value of the node */
int StateNode::getHeuristic()
{
return this->heuristic;
}
/* Prints the state with a nice like board for better visualization */
void StateNode::printState()
{
for (int i = 0; i < this->size; i++)
std::cout << " ____";
std::cout << std::endl;
for (int i = 0; i < this->size; i++)
{
for (int j = 0; j < this->size; j++)
{
if (j < this->size - 1)
{
std::cout << "| " << state[i][j] << " ";
}
else
{
std::cout << "| " << state[i][j] << " |";
}
}
std::cout << std::endl;
for (int k = 0; k < this->size; k++)
std::cout << "|____";
std::cout << "|\n";
}
}
/* Returns a copy of the nodes state */
char ** StateNode::getState()
{
return state;
}
Your current code allocates dynamically allocated memory, but doesn't have a coherent sense of who owns what pointer(s). It then becomes cumbersome to figure out when, where, and who is responsible for freeing the memory. To fix such code may require more error-prone logic to figure to attempt to straighten out the mess.
Instead of this, using C++ and "new-less" code, the following is more or less the equivalent of your current code:
#include <vector>
typedef std::vector<std::vector<char>> Char2D;
class StateNode
{
private:
char2D state;
int size;
int heuristic;
public:
StateNode(const Char2D& theState, int theSize);
int getHeuristic();
void printState();
Char2D& getState() { return state; }
};
Then your constructor lools like this:
StateNode::StateNode(const Char2D& theState, int theSize) :
state(theState),
size(theSize),
heuristic(NQueens::CalcHeuristic(state, size)) {}
Of course, your NQueens::CalcHeuristic has to take a Char2D (by reference) instead of a char**.
Then the rest of the implementation can look like this:
bool finished = false;
size = getNumQueens();
// Make dynamic 2D array of the specified size
Char2D init(size, std::vector<char>(size));
// Puzzle main loop
while (!finished)
{
// Randomize the queens placement on the board
randomizeGame(init, size);
// Make the initial state with the current game board
StateNode initState(init, size);
// Run the hillclimbing algo
finishState = HillClimbing<StateNode>::Run(initState, size);
// Check to see if the algo returned a valid end state
if (finishState.getHeuristic() == 0)
finished = true;
}
The initState and finishState are two distinct objects. Also, no need for the else block.
I know this is somewhat different than your original code, but the goal should be to use value types and if need be, smart pointers (which I didn't see a need here). Using types as the aforementioned ones is one way to not have issues as your facing now.
If you still want to go the pointer route, I would still leave the vector alone, and make the following changes:
#include <memory>
//...
std::unique_ptr<StateNode> finishState;
// Puzzle main loop
while (!finished)
{
// Randomize the queens placement on the board
randomizeGame(init, size);
// Make the initial state with the current game board
std::unique_ptr<StateNode> initState = std::make_unique<StateNode>(init, size);
// Run the hillclimbing algo
finishState.reset(HillClimbing<StateNode>::Run(initState, size));
// Check to see if the algo returned a valid end state
if (finishState->getHeuristic() == 0)
finished = true;
}
There is no leak in this code, as we are using std::unique_ptr, which automatically deallocates the memory for you when either the pointer goes out of scope, or reset is called.
You can debug through no-source-available into your code. Get vs to show disassembly and f11 into next function.
Vs has debug heap with leak detection. That can help, but also cause slow down, and earlier crash. Compile with different C runtime to gain/lose that feature.
Application verifier also has good leak detection, showing stacks of leaked allocations. this is what I use

Adding element to array of struct c++

Can someone explain why this code does not work? It keeps crashing when it asks for input in addCar().
I think something is wrong with copying an array, but I can't figure out what exactly. I also tried to use copy() but it didn't work either.
#include <iostream>
#include <string>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
struct Car{
string Brand;
string model;
long mileage;
};
void addCar(int *ptr, struct Car *arra){
*ptr=*ptr+1;
Car *newArr = new Car[*ptr];
memcpy(newArr, arra, (*ptr)*sizeof(Car));
cout<<"Brand ";
getline(cin,newArr[*ptr].Brand);
cout<<"Model ";
getline(cin, newArr[*ptr].model);
cout<<"mileage ";
cin>>newArr[*ptr].mileage;
arra=newArr;
};
int main(int argc, char** argv) {
int size=1;
int *ptr_size;
ptr_size=&size;
Car *tab=new Car[*ptr_size];
tab[0].Brand = "Audi";
tab[0].model = "A8";
tab[0].mileage = 14366;
addCar(*ptr_size, tab);
return 0;
}
The fail is probably here:
getline(cin,newArr[*ptr].Brand);
A bit above, you did this: *ptr=*ptr+1; and made newArr an array of *ptr elements. Arrays are origin zero. That means the first item in the array is newArr[0]. The last will be at newArr[*ptr-1], so writing into newArr[*ptr] is writing over someone else's memory. Generally a bad thing to do.
But this is also not cool:
*ptr=*ptr+1;
Car *newArr = new Car[size+1];
memcpy(newArr, arra, (*ptr)*sizeof(Car));
You increment the size of the array. That's OK.
You create a new array with the new size. That's OK.
You copy new size number of elements from the old array to the new array and over shoot the end of the old array. Not OK.
The best answer is given by Jerry Coffin and Paul McKenzie in the comments: use a std::vector. If this is not allowed... Ick.
But alrighty then.
First, memcpy literally copies a block of memory. It does not know or care what that block of memory is or what it contains. Never use memcpy unless you are copying something really, really simple like basic data type or a structure made up of nothing but basic data types. String is not basic. The data represented by a string might not be inside the string. In that case, you copy a pointer to the string and that pointer will not be valid after the death of the string. That's not a problem in your case because you don't kill the string. That leads to problem 2. Let's fix that before you get there. The easiest way (other than vector) is going to be:
for (int index = 0; index < *ptr-1; index++)
{
newArr[index] = arra[index];
}
An optimization note. You don't want to resize and copy the array every time you add to it. Consider having two integers, one size of array and the other index into array and double the size of the array every time the index is about to catch up with the size.
When you allocate any memory for data with new somebody has to clean up and put that memory back with delete. In C++ that somebody is you. so, before you arra=newArr; you need to delete[] arra;
Passing in the array index as a pointer overcomplicates. Use a reference or just pass by value and return the new index. Also, don't name a variable ptr. Use something descriptive.
void addCar(int &arrasize, struct Car *arra){
or
int addCar(int arrasize, struct Car *arra){
Next problem: int addCar(int arrasize, struct Car *arra){ passes in a pointer to arra. But you passed the pointer by value, made a copy of the pointer, so when you change the pointer inside the function, it's only the copy that got changed and the new array is not going to come back out again. So,
int addCar(int arrasize, struct Car * & arra){
Passes in a reference to the pointer and allows you to modify the pointer inside the function.
Putting all that together:
int addCar(int size, struct Car * & arra)
{
Car *newArr = new Car[size + 1];
for (int index = 0; index < size; index++)
{
newArr[index] = arra[index];
}
cout << "Brand ";
getline(cin, newArr[size].Brand);
cout << "Model ";
getline(cin, newArr[size].model);
cout << "mileage ";
cin >> newArr[size].mileage;
delete[] arra;
arra = newArr;
return size+1;
}
int main()
{
int size=1;
Car *tab=new Car[size];
tab[0].Brand = "Audi";
tab[0].model = "A8";
tab[0].mileage = 14366;
size = addCar(size, tab);
// do more stuff;
// bit of test code here
for (int index = 0; index < size; index++)
{
cout << "Car " << index << " brand =" <<tab[index].Brand << " Model=" << tab[index].model << " mileage=" <<tab[index].mileage << endl;
}
delete[] tab;
return 0;
}
When you are copying the old array to the new one you are accessing invalid memory, remember that, in that point, arra has size *ptr-1 not *ptr, so the line should be
memcpy(newArr, arra, (*ptr-1)*sizeof(Car));
also in the other lines you should insert the new value in the *ptr-1 position because the indexes in newArr go from 0 to size-1 ie *ptr-1:
cout<<"Brand ";
getline(cin,newArr[*ptr-1].Brand);
cout<<"Model ";
getline(cin, newArr[*ptr-1].model);
cout<<"mileage ";
cin>>newArr[*ptr-1].mileage;

C++ Multidimensional arrays generating segmentation faults?

I am writing a script which must copy some names into a multidimensional array, print the contents of the array and then deallocate the memory and terminate. The problem I am having is that when I run the script it only prints out the last name entered. Here is what I have done. Any help would be great! Thanks in advance!
#include <iostream>
#include <string.h>
using namespace std;
void createArray(int n);
void addDetail(char*& name, char*& surname);
void printArray();
void clear();
char ***details;
int used;
int size;
int main()
{
createArray(3);
char* tmpName = new char[20];
char* tmpSurName = new char[120];
strcpy(tmpName, "nameA");
strcpy(tmpSurName, "surnameA");
addDetail(tmpName,tmpSurName);
strcpy(tmpName, "nameB");
strcpy(tmpSurName, "surnameB");
addDetail(tmpName,tmpSurName);
strcpy(tmpName, "nameC");
strcpy(tmpSurName, "surnameC");
addDetail(tmpName,tmpSurName);
clear();
return 0;
}
void createArray(int n)
{
details= new char**[n];
for(int i=0; i<n; i++)
details[i] = new char*[2];
size = n;
used = 0;
}
void addDetail(char*& name, char*& surname)
{
if(occupation < size)
{
details[used][0] = name;
details[used][1] = surname;
used++;
}else{
cout << "Array Full " << endl;
}
}
void printArray()
{
for(int i=0; i<used; i++)
cout << details[i][0] << " " << details[i][1] << endl;
}
void clear()
{
for(int i=0; i<size; i++)
{
delete [] details[i];
details[i] = 0;
}
delete [] details;
details=0;
}
You didn't allocate memory for details[used][0] and details[used][1] so it's using whatever random address was in those locations.
Since this is C++ you can use string instead perhaps? std::string **details;. This should work with your existing code, except that it will leak memory.
Better still is to use a vector of vectors.
Something like:
std::vector<std::vector<std::string> > details;
Then the createArray function can go away completely and addDetail becomes simpler:
std::vector<string> newName;
newName.push_back(name);
newName.push_back(surname);
details.push_back(newName);
It is because each time, you are effectively storing the pointer tmpName and tmpSurName in the array details. Then in the next iteration, you overwrite the contents of the memory where tmpName and tmpSurName point to, so at the end you'll have a list that contains the last name/surname n times.
To solve it, you need to re-allocate tmpName and tmpSurName before each call to addDetail.
Btw, why do you need to use an (ewww) char***, and can't use e.g. the STL?
What it looks like is happening is that you are not adding the string to the array, you are adding a pointer to name and surname. Every instance is pointing at that variable, so when you ask the array what it contains it goes and asks name and surname, which will only contain the last value.
Also that array, are you sure its working how you want it to work? Arrays are... concrete things. Your essentially saying "I want 5 of these, they will be this big (based on the type you put in)" and the computer quietly goes "well I'll set aside space for those here and you can put them in when your ready". When your code puts those names in there, there really isn't any prep on where to store them. If you fill up that space and go beyond you go to bad places. So what you should do is have that last * of char*** be a pointer to a char[120] so that you know (for your purposes atleast) it never gets filled up. Do that in your createArray function after you have created the outer arrays.
You keep overwriting your temporary buffers rather than making new buffers for each entry in the array. As a result, only the last data written to the buffer survives.
Here's a rough guide on one way to fix it, though this sample may have some problems - I made no attempt to compile or test this.
This portion of main belongs in addDetail:
char* tmpName = new char[20];
char* tmpSurName = new char[120];
strcpy(tmpName, "nameA");
strcpy(tmpSurName, "surnameA");
So, your new addDetail would look something like:
void addDetail(char*& name, char*& surname)
{
if(occupation < size)
{
details[used][0] = new char[20];
details[used][1] = new char[120];
strcpy(details[used][0], name);
strcpy(details[used][1], surname);
used++;
}else{
cout << "Array Full " << endl;
}
}
And it would be called from main like:
addDetail("nameA", "surnameA");
You'd need to update clear to properly cleanup the allocations made in addDetail though.