I am using visual studio to code with, and I do not understand why i am getting the error "Error C6001 - Using uninitialized memory '*tempPtr' " at only the line right below the else if condition statement.
void removeNumber(double*& arrayPtr, double number, int& size) {
bool found = false;
double* tempPtr = new double[size-1];
for (int i = 0; i < size; i++) {
if (arrayPtr[i] == number) {
found = true;
}
else if (found == false && arrayPtr[i] != number) {
arrayPtr[i] = tempPtr[i];
}
else {
arrayPtr[i] = tempPtr[i - 1];
}
} delete[] arrayPtr;
arrayPtr = tempPtr;
--size;
}
arrayPtr[i] = tempPtr[i];
In this line, you try to assign an uninitialized tempPtr[i] to an initialized arrayPtr[i]. It should be the other way around. However, if what you want to do is to assign a null pointer to arrayPtr[i], you can initialize tempPtr with null pointers.
This is not related to the question but I notice at the end you de-allocate the memory for arrayPtr and then use arrayPtr. This will crash your program at run-time. You only want to de-allocate when you have no use for it anymore.
Related
I have a MultiString class that has some methods in it.
I am strugling with deleting my array of strings in the destructor, I get heap corruption.
Here is my class (some methods are cut)
class MultiString {
public:
//constructor destructor
MultiString(int);
~MultiString();
//methods
void Setat(int nindex, const char* str);
//attributes
char** buf;//pointer to vector
int str_nmb;//strings number
};
Constructor code:
MultiString::MultiString(int number)
{
str_nmb = number;
buf = new char* [number];
for (int i = 0; i < number; i++) buf[i] = NULL;
}
Setat code (used to set strings in array):
void MultiString::Setat(int nindex, const char* str)
{
if (nindex<0 || nindex>str_nmb || str == NULL) {
std::cout << "gg";
return;
}
char* tmp = new char[strlen(str)+1];
if (tmp == NULL) return;
if (buf[nindex] != NULL) delete buf[nindex]; //here delete works fine
buf[nindex] = tmp;
strcpy_s(buf[nindex], strlen(buf[nindex]), str);
std::cout << buf[nindex]<< std::endl;
}
Destructor code:
MultiString::~MultiString()
{
for (int i = 0; i < str_nmb; i++)
delete buf[i]; // heap corruption here
delete buf;
}
And my main():
int main()
{
MultiString* ms = new MultiString(3);
ms->etat(0, "qwerty");
ms->Setat(1, "asdfgh");
ms->Setat(2, "zxcvbn");
delete ms;
return 0;
}
char* tmp = new char[strlen(str)+1];
// ...
buf[nindex] = tmp;
strcpy_s(buf[nindex], strlen(buf[nindex]), str);
buf[nindex] points to the freshly allocated, but uninitialized memory area. Calling strlen on that is undefined behavior and likely what corrupts your heap. You probably want to call strlen(str) instead.
Apart from that you're making a few other mistakes:
Rule of 0/3/5 broken.
delete where delete[] would be necessary
Wrong bounds check (nindex>str_nmb)
What about Multistring(-5) ?
if (tmp == NULL) return; ... no, you shouldn't mute errors. Throw an exception or something.
Also .. why strcpy_s ? Use std::strncpy ... that's at least guaranteed to be available! Make sure the copied C string is null terminated!
I met huge problem with memory leaks and I don't know where to put that "delete" to get rid of them. Below is part of my code, and there is a full one: https://pastebin.com/Wtk83nuH.
string* startowa(int& rozmiar)
{
rozmiar = 5;
string* tablica = new string[rozmiar];
for (int i = 0; i < rozmiar; i++)
tablica[i] = "text";
return tablica;
}
string* plusx(string* tab, int& rozmiar)
{
string tekst = "something";
string* tablica_3 = new string[rozmiar];
tablica_3[rozmiar - 1] = tekst;
for (int i = 0; i<rozmiar - 1; i++)
tablica_3[i] = tab[i];
return tablica_3;
}
string* minusx(string* tab, int& rozmiar)
{
string* tablica_3 = new string[rozmiar];
for (int i = 0; i < rozmiar; i++)
tablica_3[i] = tab[i];
return tablica_3;
}
int main()
{
int wybor = 1, rozmiar = 1;
string *tablica = startowa(rozmiar);
while (wybor != 55) {
cin >> wybor;
if (wybor == 1) {
rozmiar++;
tablica = plusx(tablica, rozmiar);
}
if (wybor == 6) wybor = 55;
else {
rozmiar--;
tablica = minusx(tablica, rozmiar);
}
// there were other "ifs" but its just a part of the code
}
for (int i = 0; i < rozmiar; i++)
cout << tablica[i] << endl;
delete[] tablica;
cin >> wybor;
getchar();
return 0;
}
The memory leak is your least problem in that source code. In fact, you don't need heap allocations at all in your example.
Here are some fast improvements:
- use "std::string" instead of just string, I guess you are using "using namespace std"
- do not return a pointer to string, you can just declare a string and return it
- do not use a reference to an int as a function parameter if you are not returning it
- use const as much as you can
- replace "string *" with "const string&" if you are not returning it
- do not allocate string on heap (with new), instead declare it on stack
- use vectors
You can use this great site and Scott Meyers books for other C++ good practices.
To prevent memory leaks like that, avoid manual memory management. There are a lot of tools available to you.
For example, take your string array:
string* startowa(int& rozmiar) {
rozmiar = 5;
string* tablica = new string[rozmiar];
// ...
}
This should be replaced by std::vector. And since a vector keep track of it's size, you don't need to pass the size as reference:
std::vector<std::string> startowa() {
// ...
std::vector<std::string> tablica(5);
// ...
}
Then, your function that operates on the array should take the vector by reference to about copies, and return another vector. Since a vector already has a function that insert a new element, your plusx function becomes this:
void plusx(std::vector<std::string>& tab) {
std::string tekst = "something";
tab.emplace_back(std::move(tekst));
}
And your minusx function becomes that:
void minusx(std::vector<std::string>& tab) {
tab.pop_back();
}
By the way, with a vector, you can completely remove your startowa function by replacing the call in your main by this:
// Was `string *tablica = startowa(rozmiar);`
std::vector<std::string> tablica(5, "text");
Since std::vector manages it's memory itself, you don't need to delete it anywhere.
If you don't want to use vector, you can alway use std::unique_ptr<std::string[]>. The only difference in you code would be to send tablica.get() to your functions, and use std::make_unique<std::string[]>(rozmiar) instead of new std::string[rozmiar]
The correct answer is use std::vector. For example:
vector<string> startowa(int& rozmiar)
{
rozmiar = 5;
vector<string> tablica(rozmiar);
for (int i = 0; i < rozmiar; i++)
tablica[i] = "text";
return tablica;
}
Note the return by value. Don't fall into the trap of thinking you're saving processing time by returning by reference. That vector goes out of scope and is destroyed at the end of the function. With a returned reference the best you can hope for is the caller receiving a load of garbage and crashing before any damage can be done.
A decent compiler will eliminate the copying when you return the vector by value, and if the compiler decides that it cannot, std::move will take care of that.
vector also knows how big it is, eliminating the need for rozmiar.
Now... What went wrong? Let's look at the code
int main()
{
int wybor = 1, rozmiar = 1;
string * tablica = startowa(rozmiar);
startowa allocated an array of strings and stored a pointer to the array in tablica.
while (wybor != 55)
{
cin >> wybor;
if (wybor == 1)
{
rozmiar++;
tablica = plusx(tablica, rozmiar);
plusx allocated a new array of strings, a pointer to which has been returned and written over the pointer returned by startowa. startowa's array is now effectively lost, leaked, as it is next to impossible to find again to delete[].
We would need to delete[] tablica; before making the assignment. Clearly we can't do this before calling plusx as tablica is a parameter, so we need to store a temp.
string * temp = plusx(tablica, rozmiar);
delete[] tablica;
tablica = temp;
But what if something unexpected happens and an exception is thrown? The code never hits the delete[] and BOTH allocations are lost. vector handles all this for you.
And back to the code
}
if (wybor == 6)
wybor = 55;
else
{
rozmiar--;
tablica = minusx(tablica, rozmiar);
Same problem and solution as above.
}
// there were other "ifs" but its just a part of the code
}
for (int i = 0; i < rozmiar; i++)
cout << tablica[i] << endl;
delete[] tablica;
One of an in-determinant number of allocations is released here. The rest are lost.
cin >> wybor;
getchar();
return 0;
}
I'm having a problem with the code attached below. Essentially it generates a huge memory leak but I can't see where it happens.
What the code does is receiving an array of strings, called prints, containing numbers (nodes) separated by ',' (ordered by desc number of nodes), finding other compatible prints (compatible means that the other string has no overlapping nodes 0 excluded because every print contains it) and when all nodes are covered it calculates a risk function on the basis of a weighted graph. In the end it retains the solution having the lowest risk.
The problem is that leak you see in the picture. I really can't get where it comes from.
Here's the code:
#include "Analyzer.h"
#define INFINITY 999999999
// functions prototypes
bool areFullyCompatible(int *, int, string);
bool contains(int *, int, int);
bool selectionComplete(int , int);
void extractNodes(string , int *, int &, int);
void addNodes(int *, int &, string);
Analyzer::Analyzer(Graph *graph, string *prints, int printsLen) {
this->graph = graph;
this->prints = prints;
this->printsLen = printsLen;
this->actualResult = new string[graph->nodesNum];
this->bestResult = new string[graph->nodesNum];
this->bestReSize = INFINITY;
this->bestRisk = INFINITY;
this-> actualSize = -1;
}
void Analyzer::getBestResult(int &size) {
for (int i = 0; i < bestReSize; i++)
cout << bestResult[i] << endl;
}
void Analyzer::analyze() {
// the number of selected paths is at most equal to the number of nodes
int maxSize = this->graph->nodesNum;
float totRisk;
int *actualNodes = new int[maxSize];
int nodesNum;
bool newCycle = true;
for (int i = 0; i < printsLen - 1; i++) {
for (int j = i + 1; j < printsLen; j++) {
// initializing the current selection
if (newCycle) {
newCycle = false;
nodesNum = 0;
extractNodes(prints[i], actualNodes, nodesNum, maxSize);
this->actualResult[0] = prints[i];
this->actualSize = 1;
}
// adding just fully compatible prints
if (areFullyCompatible(actualNodes, nodesNum, prints[j])) {
this->actualResult[actualSize] = prints[j];
actualSize++;
addNodes(actualNodes, nodesNum, prints[j]);
}
if (selectionComplete(nodesNum, maxSize)) {
// it means it's no more a possible best solution with the minimum number of paths
if (actualSize > bestReSize) {
break;
}
// calculating the risk associated to the current selection of prints
totRisk = calculateRisk();
// saving the best result
if (actualSize <= bestReSize && totRisk < bestRisk) {
bestReSize = actualSize;
bestRisk = totRisk;
for(int k=0;k<actualSize; k++)
bestResult[k] = actualResult[k];
}
}
}
newCycle = true;
}
}
float Analyzer::calculateRisk() {
float totRisk = 0;
int maxSize = graph->nodesNum;
int *nodes = new int[maxSize];
int nodesNum = 0;
for (int i = 0; i < actualSize; i++) {
extractNodes(this->actualResult[i], nodes, nodesNum, maxSize);
// now nodes containt all the nodes from the print but 0, so I add it (it's already counted but misses)
nodes[nodesNum-1] = 0;
// at this point I use the graph to calculate the risk
for (int i = 0; i < nodesNum - 1; i++) {
float add = this->graph->nodes[nodes[i]].edges[nodes[i+1]]->risk;
totRisk += this->graph->nodes[nodes[i]].edges[nodes[i+1]]->risk;
//cout << "connecting " << nodes[i] << " to " << nodes[i + 1] << " with risk " << add << endl;
}
}
delete nodes;
return totRisk;
}
// -------------- HELP FUNCTIONS--------------
bool areFullyCompatible(int *nodes, int nodesNum, string print) {
char *node;
char *dup;
int tmp;
bool flag = false;
dup = strdup(print.c_str());
node = strtok(dup, ",");
while (node != NULL && !flag)
{
tmp = atoi(node);
if (contains(nodes, nodesNum, tmp))
flag = true;
node = strtok(NULL, ",");
}
// flag signals whether an element in the print is already contained. If it is, there's no full compatibility
if (flag)
return false;
delete dup;
delete node;
return true;
}
// adds the new nodes to the list
void addNodes(int *nodes, int &nodesNum, string print) {
char *node;
char *dup;
int tmp;
// in this case I must add the new nodes to the list
dup = strdup(print.c_str());
node = strtok(dup, ",");
while (node != NULL)
{
tmp = atoi(node);
if (tmp != 0) {
nodes[nodesNum] = tmp;
nodesNum++;
}
node = strtok(NULL, ",");
}
delete dup;
delete node;
}
// verifies whether a node is already contained in the nodes list
bool contains(int *nodes, int nodesNum, int node) {
for (int i = 0; i < nodesNum; i++)
if (nodes[i] == node)
return true;
return false;
}
// verifies if there are no more nodes to be added to the list (0 excluded)
bool selectionComplete(int nodesNum, int maxSize) {
return nodesNum == (maxSize-1);
}
// extracts nodes from a print add adds them to the nodes list
void extractNodes(string print, int *nodes, int &nodesNum, int maxSize) {
char *node;
char *dup;
int idx = 0;
int tmp;
dup = strdup(print.c_str());
node = strtok(dup, ",");
while (node != NULL)
{
tmp = atoi(node);
// not adding 0 because every prints contains it
if (tmp != 0) {
nodes[idx] = tmp;
idx++;
}
node = strtok(NULL, ",");
}
delete dup;
delete node;
nodesNum = idx;
}
You have forgotten to delete several things and used the wrong form of delete for arrays where you have remembered, e.g.
float Analyzer::calculateRisk() {
float totRisk = 0;
int maxSize = graph->nodesNum;
int *nodes = new int[maxSize];
//...
delete [] nodes; //<------- DO THIS not delete nodes
The simplest solution is to avoid using raw pointers and use smart ones instead. Or a std::vector if you just want to store stuff somewhere to index into.
You have new without corresponding delete
this->actualResult = new string[graph->nodesNum];
this->bestResult = new string[graph->nodesNum];
These should be deleted somewhere using delete [] ...
You allocate actualNodes in analyze() but you don't release the memory anywhere:
int *actualNodes = new int[maxSize];
In Addition, Analyzer::bestResult and Analyzer::actualResult are allocated in the constructor of Analyzer but not deallocated anywhere.
this->actualResult = new string[graph->nodesNum];
this->bestResult = new string[graph->nodesNum];
If you must use pointers, I really suggest to use smart pointers, e.g. std::unique_ptr and/or std::shared_ptr when using C++11 or later, or a Boost equivalent when using C++03 or earlier. Otherwise, using containers, e.g. std::vector is preferred.
PS: You're code also has a lot of mismatches in terms of allocation and deallocation. If memory is allocated using alloc/calloc/strdup... it must be freed using free. If memory is allocated using operator new it must be allocated with operator delete. If memory is allocated using operator new[] it must be allocated with operator delete[]. And I guess you certainly should not delete the return value of strtok.
I'm doing something with VoidPtr and when i tested out my codes on other IDE such as Quincy or Eclipse, I don't have any problem running them.
However, when i tried to run my codes in Visual Studio 2015, the display is fine, but i stumbled upon an error called
HEAP CORRUPTED DETECTED: after Normal block #138 at (some address)
I can't locate where is the error because it is displaying the address of a pointer which is even harder for me to debug.
I'm trying to union the data of 2 void pointer array.
void unionAnimalArray(VoidPtr* animalArray, int size, VoidPtr* animalArray2, int size2)
{
int sizeu;
VoidPtr *vpArray = &animalArray[0];
VoidPtr *vpArray2 = &animalArray2[0];
VoidPtr *end = &animalArray2[size2];
VoidPtr *su = new VoidPtr[12];
su = animalArray;
sizeu = size;
VoidPtr tempu;
bool check;
while (vpArray2 != end)
{
do
{
tempu = *vpArray2;
check = true;
for (int j = 0; j<size; j++)
{
if (j == 0)
vpArray = &animalArray[0];
if (*(static_cast<Animal*>(tempu)) == *(static_cast<Animal*>(*vpArray)))
{
check = false;
break;
}
++vpArray;
}
if (!check)
++vpArray2;
} while (!check && vpArray2 != end);
if (vpArray2 != end)
{
vpArray = &su[sizeu];
*vpArray = tempu;
++sizeu;
++vpArray2;
}
}
cout << "The union is" << endl;
cout << "\t{";
printAnimalArray(su, sizeu);
delete[]su;
}
void unionAnimalArray(VoidPtr* animalArray, int size, VoidPtr* animalArray2, int size2)
...
VoidPtr *su = new VoidPtr[12]; // su points to new memory
su = animalArray; // su now points to same memory as animalArray2
...
delete[]su; // deletes memory shared with animalArray2
An array should be copied element-wise instead of assignment:
for(int i = 0; i < size2; ++i) {
su[i] = animalArray[i];
}
You can keep buffer su in automatic memory as you know the size of buffer in compile time:
VoidPtr su[12];
Think a little bit about this:
VoidPtr *su = new VoidPtr[12];
su = animalArray;
Where did the 12 new VoidPtr-s go?
Who and when they will be deleted ?
I have a constructor, that receives a character pointer. If it is empty, I need to set its member variable to NULL, however, the program crashes on exit when I try to.
I have verified that it gets to the line where it sets it to NULL and that is the cause of the crash.
I've tried the following:
val = NULL;
val = 0;
val = "";
Those all cause a crash, however if I used:
val = new Char[1];
val = "o";
it didn't crash.
Is there something that I'm not doing?
Update:
Here is a quick update to my problem.
The destructor I'm using is:
~LField() {
if (val)
delete[] val;
}
If I take out:
if (val)
delete[] val;
then the program doesn't crash on exit with:
val = "";
Here is some more code as requested:
LField(int rowNumVal, int colNumVal, int widthVal, const char *valVal = "", bool canEditVal = true) {
if(strlen(valVal) > 0) {
//doesn't jump in here since valVal is empty
}
else {
val = ""; // this is where I'm trying to set a NULL value
}
}
LField(const LField &clone) {
if (val)
delete[] val;
val = new char[strlen(clone.val)];
strcpy(val, clone.val);
rowNum = clone.rowNum;
colNum = clone.colNum;
width = clone.width;
canEdit = clone.canEdit;
index = clone.index;
}
LField& operator=(const LField &lfieldobj) {
if (this != &lfieldobj) {
if (val)
delete[] val;
val = new char[strlen(lfieldobj.val)];
strcpy(val, lfieldobj.val);
rowNum = lfieldobj.rowNum;
colNum = lfieldobj.colNum;
width = lfieldobj.width;
canEdit = lfieldobj.canEdit;
index = lfieldobj.index;
}
return *this;
}
Modified:
LField(int rowNumVal, int colNumVal, int widthVal, const char *valVal = NULL, bool canEditVal = true) {
if(valVal != NULL) {
}
else {
val = NULL;
}
}
LField(const LField &clone) {
delete[] val;
if (clone.val != NULL) {
val = new char[strlen(clone.val) + 1];
strcpy(val, clone.val);
}
else
val = NULL;
rowNum = clone.rowNum;
colNum = clone.colNum;
width = clone.width;
canEdit = clone.canEdit;
index = clone.index;
}
LField& operator=(const LField &lfieldobj) {
if (this != &lfieldobj) {
delete[] val;
if (lfieldobj.val != NULL) {
val = new char[strlen(lfieldobj.val) + 1];
strcpy(val, lfieldobj.val);
}
else
val = NULL;
rowNum = lfieldobj.rowNum;
colNum = lfieldobj.colNum;
width = lfieldobj.width;
canEdit = lfieldobj.canEdit;
index = lfieldobj.index;
}
return *this;
}
~LField() {
delete[] val;
}
I've updated the code. Now val is either allocated memory with new[] or it is NULL, so there shouldn't be a problem with delete[]. However, it still crashes on exit.
In the copy constructor you try to delete[] an uninitialized pointer:
LField(const LField &clone) {
//good code here, then...
if (val) //<+ some random address here
delete[] val;//<-undefined behavior
}
just don't do that, skip the whole construct. The copy constructor is invoked on an unitilialized object, there're no resources to "free" yet.
Also you try to delete[] a string literal, that's undefined behavior. Try the following change:
LField(int rowNumVal, int colNumVal, int widthVal, const char *valVal = "", bool canEditVal = true) {
if(strlen(valVal) > 0) {
//doesn't jump in here since valVal is empty
}
else {
val = new char[1];
*val = 0;
}
}
also the following is a buffer overrun:
val = new char[strlen(whatever)]; <-forgot to +1 for the null terminator
strcpy(val, whatever);
also checking for a null pointer before delete[] is unnecessary - delete[] on a null pointer is legal and has no effect.
Oh dear, where to start??
a:
LField(const LField &clone) {
if (val)
delete[] val;
This is daft, as val is undefined. You will be calling delete[] on random memory.
b:
val = new char[strlen(clone.val)];
strcpy(val, clone.val);
c-type Strings need a null terminator. You need to new[] and additional byte.
Probably somewhere in your code you are trying to access(dereference) val which still refers to NULL.
Make sure no where in your code you are doing this
val=NULL; //in the constructor
//somewhere in your code
char ch= *val; //This would be Undefined Behavior
EDIT
You are calling delete[] on val whose value is ""(string literal), that is undefined behavior.
Some examples of UB
1)
char *p="hello";
delete p; //UB
delete []p; //UB
2)
char *p==new char[20]("Hello");
delete p; //UB
delete []p; //fine
3)
char *p=new char('a');
delete []p; //UB
delete p; //fine
Calling
delete[] NULL;
delete[] 0;
is ok, you don't even need the null-check.
But calling
delete[] "whatever";
is not OK since this char* wasn't allocated with new[].
Note that calling string function like strlen() like it is done in your constructor is illegal in a null reference.
You access val in your constructor before it is assigned the first time. This can also cause undefined behaviour.
I'm with Prasoon Saurav. The code you showed looks good, so the problem is somewhere else.
Try this:
Change it back to val = 0;
Remove all your code except the constructor, the destructor, and a declaration of an object of that class. Comment out everything else. I'd wager good repuation that it won't crash.
Slowly uncomment your other code and retry the program. When it crashes again, you've found the culprit.