Error in deleting a dynamic object? - c++

I am allocating a memory for union in heap and i need to delete the object of union when the element Id of union is 900.
Please help me to delete groupUnion[i] object when the Id is 900
below is my code.
groupUnion = (SettingsUnion *) malloc(sizeof(SettingsUnion) * (NumAttrs + 1));
if(groupUnion == (SettingsUnion *) NULL)
{
return (FALSE);
}
for (unsigned int i=0; i < NumAttrs; i++)
{
inFile.read(reinterpret_cast<char*>(&groupUnion[i]),sizeof(SettingsUnion));
if(groupUnion[i].Id == 900)
{
free groupUnion[i]; // this is bad how can i delete groupUnion[i] when groupUnion[i].Id == 900
groupUnion[i] = NULL;
}
}
inFile.close()
Thanks in Advance!!

Your code fragment free groupUnion[i];groupUnion[i] = NULL lets me assume that you actually want to express an array of pointers to SettingUnion-objects rather than an array of SettingUnion-objects.
So your code could look like as follows (I used your malloc/free-style, though in C++ you actually would use new/delete):
groupUnion = (SettingsUnion **) malloc(sizeof(SettingsUnion*) * (NumAttrs + 1));
if(groupUnion == NULL)
{
return (FALSE);
}
for (unsigned int i=0; i < NumAttrs; i++)
{
groupUnion[i] = malloc(sizeof(SettingsUnion));
inFile.read(reinterpret_cast<char*>(&groupUnion[i]),sizeof(SettingsUnion));
if(groupUnion[i]->Id == 900)
{
free groupUnion[i];
groupUnion[i] = NULL;
}
}
inFile.close()

You cannot free part of the allocated memory: free groupUnion[i]
What you can do however is to allocate individually the elements and then free them individually:
// not sure why you need the +1 (anyway you allocate an array of pointers to the struct here. Consider using new operator)
groupUnion = (SettingsUnion **) malloc(sizeof(SettingsUnion *) * (NumAttrs + 1));
if(groupUnion == (SettingsUnion *) NULL)
{
return (FALSE);
}
for (unsigned int i=0; i < NumAttrs; i++)
{
// you allocate the individual groupUnion here:
groupUnion[i] = (SettingsUnion *) malloc(sizeof(SettingsUnion));
if(groupUnion[i] == (SettingsUnion *) NULL)
{
return (FALSE);
}
inFile.read(reinterpret_cast<char*>(&groupUnion[i]),sizeof(SettingsUnion));
if(groupUnion[i].Id == 900)
{
free groupUnion[i]; // this is bad how can i delete groupUnion[i] when groupUnion[i].Id == 900
groupUnion[i] = NULL;
}
}
inFile.close()

Related

getting an error code about using uninitialized memory

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.

2D Array Memory Allocation (malloc) Returns NULL

I am trying to compile a 64-bit CPP code using GCC, however multidimensional (i.e. 2D) array memory allocation returns NULL once I increase the element size from 46,000 to 46,500. My virtual memory is set to 96GB, and hardware is running 64-bit OS using 32GB Ram. The code works fine as long as MAX_VERTICES does not exceed 46000.
Following is what I am trying to dynamically allocate:
struct ShortestPath {
real32 totalWeight;
// NOTE: ShortestPath is a list of pointers; does not make copies
// (i.e. side-effects) the pointers point to memory allocated
// in the DijkstraSPTree array in the vehicle_searching module
List<DirectedEdge *> *edgeList;
};
#define MAX_VERTICES 46500
global_variable ShortestPath spAllPairs[MAX_VERTICES][MAX_VERTICES];
Allocate Memory on the Heap to replace
spAllPairs[MAX_VERTICES][MAX_VERTICES]
with the following code
global_variable ShortestPath **spAllPairs;
global_variable ShortestPath *arr_data;
ShortestPath *getShortestPath(EdgeWeightedDigraph *digraph, int32 source,
int32 dest)
{
free(spAllPairs); // Function is called multiple times so I clear memory
free(arr_data); // before reallocation given values pointed by pointers
free(spTreesArray); // are used in other files in my project after run.
inline allocate_mem(ShortestPath*** arr, ShortestPath** arr_data, int n, int m);
allocate_mem(&spAllPairs, &arr_data, MAX_VERTICES, MAX_VERTICES);
for (unsigned int k = 0 ; k < MAX_VERTICES ; k++) {
if (spAllPairs[k] == NULL) {
while (k >= 1) {
free(spAllPairs[k]);
--k;
}
free(spAllPairs[0]);
free(spAllPairs);
fprintf(stderr, "Failed to allocate space for Shortest Path Pairs!\n");
exit(1);
}
}
spTreesArray = (DijkstraSPTree *)malloc(MAX_VERTICES * sizeof(DijkstraSPTree));
for (int32 vertexTo = 0; vertexTo < digraph->vertices; ++vertexTo) {
pathTo(&spTreesArray[source], &spAllPairs[source][vertexTo],
vertexTo);
}
return &spAllPairs[source][dest];
}
void pathTo(DijkstraSPTree *spTree, ShortestPath *shortestPath, int32 dest)
{
List<DirectedEdge *>::traverseList(freeDirectedEdge, shortestPath->edgeList);
List<DirectedEdge *>::emptyList(&shortestPath->edgeList);
shortestPath->totalWeight = spTree->distTo[dest];
}
int allocate_mem(ShortestPath ***arr, ShortestPath **arr_data, int n, int m)
{
*arr = (ShortestPath **)malloc(n * sizeof(ShortestPath*));
*arr_data = (ShortestPath *)malloc(n * m * sizeof(ShortestPath));
for (int i = 0; i < n; i++)
(*arr)[i] = *arr_data + i * m;
return 0; //free point
}
The function allocate_mem is inconsistent with the code used in getShortestPath to free the structures. If arr_data is not used elsewhere, you should remove this global variable and allocate an indirect array this way:
ShortestPath **allocate_mem(int n, int m) {
ShortestPath **arr = (ShortestPath **)calloc(n, sizeof(*arr));
if (arr != NULL) {
for (int i = 0; i < n; i++) {
arr[i] = (ShortestPath *)calloc(m, sizeof(ShortestPath));
if (arr[i] == NULL)
break;
}
}
return arr;
}
Notes:
it would be safer to store NULL into the global pointers after you free the memory they point to.
it would be more consistent for allocate_mem to check if it could allocate all the array elements and free whatever was allocated if not, instead of trying to clean up in the caller function.
Here is a more consistent version and the calling code:
ShortestPath **allocate_mem(int n, int m) {
ShortestPath **arr = (ShortestPath **)calloc(n, sizeof(*arr));
if (arr != NULL) {
for (int i = 0; i < n; i++) {
arr[i] = (ShortestPath *)calloc(m, sizeof(ShortestPath));
if (arr[i] == NULL) {
for (j = i; j-- > 0;) {
free(arr[j]);
}
free(arr);
return NULL;
}
}
}
return arr;
}
ShortestPath *getShortestPath(EdgeWeightedDigraph *digraph, int32 source,
int32 dest)
{
// Function is called multiple times so I clear memory
// before reallocation given values pointed by pointers
// are used in other files in my project after run.
free(spAllPairs);
spAllPairs = NULL;
free(arr_data);
arr_data = NULL;
free(spTreesArray);
spTreesArray = NULL;
spAllPairs = allocate_mem(MAX_VERTICES, MAX_VERTICES);
if (spAllPairs == NULL) {
fprintf(stderr, "Failed to allocate space for Shortest Path Pairs!\n");
exit(1);
}
spTreesArray = (DijkstraSPTree *)malloc(MAX_VERTICES * sizeof(DijkstraSPTree));
if (spTreesArray == NULL) {
fprintf(stderr, "Failed to allocate space for DijkstraSPTree!\n");
exit(1);
}
for (int32 vertexTo = 0; vertexTo < digraph->vertices; ++vertexTo) {
pathTo(&spTreesArray[source], &spAllPairs[source][vertexTo],
vertexTo);
}
return &spAllPairs[source][dest];
}
EDIT as M.M commented, you should use the new and delete operators in C++ instead of malloc() and free(). (or in addition to malloc, but why bother with malloc anyway):
ShortestPath **allocate_mem(int n, int m) {
ShortestPath **arr = new ShortestPath *[n];
if (arr != NULL) {
for (int i = 0; i < n; i++) {
arr[i] = new ShortestPath[m];
if (arr[i] == NULL) {
for (j = i; j-- > 0;) {
delete[] arr[j];
}
delete[] arr;
return NULL;
}
}
}
return arr;
}
ShortestPath *getShortestPath(EdgeWeightedDigraph *digraph, int32 source,
int32 dest)
{
// Function is called multiple times so I clear memory
// before reallocation given values pointed by pointers
// are used in other files in my project after run.
delete[] spAllPairs;
spAllPairs = NULL;
delete[] spTreesArray;
spTreesArray = NULL;
spAllPairs = allocate_mem(MAX_VERTICES, MAX_VERTICES);
if (spAllPairs == NULL) {
fprintf(stderr, "Failed to allocate space for Shortest Path Pairs!\n");
exit(1);
}
spTreesArray = new DijkstraSPTree *[MAX_VERTICES];
if (spTreesArray == NULL) {
fprintf(stderr, "Failed to allocate space for DijkstraSPTree!\n");
exit(1);
}
for (int32 vertexTo = 0; vertexTo < digraph->vertices; ++vertexTo) {
pathTo(&spTreesArray[source], &spAllPairs[source][vertexTo],
vertexTo);
}
return &spAllPairs[source][dest];
}

C++ memory leak, where?

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.

Is that a memory leak?

The code allocates a memory for "p" variable but I think it can't free it if there are no errors at moment of running this code. Am I right? Or it can free in somewhere else place of the program?
static NSVGparser* nsvg__createParser()
{
NSVGparser* p;
p = (NSVGparser*)malloc(sizeof(NSVGparser));
if (p == NULL) goto error;
memset(p, 0, sizeof(NSVGparser));
p->image = (NSVGimage*)malloc(sizeof(NSVGimage));
if (p->image == NULL) goto error;
memset(p->image, 0, sizeof(NSVGimage));
// Init style
nsvg__xformIdentity(p->attr[0].xform);
memset(p->attr[0].id, 0, sizeof p->attr[0].id);
p->attr[0].fillColor = NSVG_RGB(0,0,0);
p->attr[0].strokeColor = NSVG_RGB(0,0,0);
p->attr[0].opacity = 1;
p->attr[0].fillOpacity = 1;
p->attr[0].strokeOpacity = 1;
p->attr[0].stopOpacity = 1;
p->attr[0].strokeWidth = 1;
p->attr[0].strokeLineJoin = NSVG_JOIN_MITER;
p->attr[0].strokeLineCap = NSVG_CAP_BUTT;
p->attr[0].fillRule = NSVG_FILLRULE_NONZERO;
p->attr[0].hasFill = 1;
p->attr[0].visible = 1;
return p;
error:
if (p) {
if (p->image) free(p->image);
free(p);
}
return NULL;
}
The client code is expected to call the nvsg_deleteParser() function after using the returned parser in order to free its allocated resources:
NSVGparser *parser = nsvg__createParser();
if (parser)
{
...
nvsg_deleteParser(parser);
}

passing pointer to function and using realloc

I want to pass a pointer to a function which will call a second function that will use realloc.
The issue is that realloc is returning NULL.
I don't know if the mistake is in the numbers of * in the function call or something else.
Could you please help me ?
The code:
int main(){
// some code.
clause_t* ptr; //clause_t is a structure i declared.
//Some work including the initial allocation of ptr (which is working).
assignLonely(matSAT, ic.nbClause, ic.nbVar, ptr); //the issue is here.
//Some other work
}
void assignLonely(int** matSAT, int nbClause, int nbVar, clause_t* ptr)
{
int i = 0, j = 0;
int cpt = 0;
int indice = -1;
for (i = 0; i < nbClause ; ++i)
{
j = 0;
cpt = 0;
while((j < nbVar) && (cpt < 2))
{
if (matSAT[i][j] != 0)
{
cpt++;
}
else
{
indice = j;
}
if (cpt < 2)
{
deleteClause(indice, &ptr);
}
j++;
}
}
}
void deleteClause(int indiceClause, clause_t** ptr)
{
int i = indiceClause;
int nbElt = sizeof((*ptr))/sizeof((*ptr)[0]);
int tailleElt = sizeof((*ptr)[0]);
while(i+1 < nbElt)
{
(*ptr)[i] = (*ptr)[i+1];
i++;
}
*ptr = (clause_t*)realloc(*ptr, (nbElt-1)*tailleElt);
if (*ptr == NULL)
{
fprintf(stderr, "Erreur reallocation\n");
exit(EXIT_FAILURE);
}
}
You have to declarae function assignLonely similarly to function deleteClause like
void assignLonely(int** matSAT, int nbClause, int nbVar, clause_t** ptr);
if you want that changes of ptr in the function would be stored in the original object in main.
Also take into account that this statement
int nbElt = sizeof((*ptr))/sizeof((*ptr)[0]);
is wrong.
Expression sizeof((*ptr)) will return the size of the pointer. Pointers do not keep information about how many elements in arrays they point to.
So expression
(nbElt-1)
can be equal to zero or even be negative.