std::unordered_map how to free struct created with malloc. Are 2 queries into the map required? - c++

The following block of code seems to run fine
Generates:
Add 1000 things
_MyMap now holds [1000] things
_MyMap free'd and erased. size now [0]
#include <unordered_map>
#include <iostream>
typedef struct _entry
{
int now;
} ENTRY, * PENTRY;
std::unordered_map<int, PENTRY> _MyMap;
typedef std::unordered_map<int, PENTRY>::iterator itEntry;
int Now()
{
return 10;
}
main function, adding comments because the site won't let me just add code
int main()
{
PENTRY pE = NULL;
std::pair<itEntry, bool> r;
printf("Add 1000 things\n");
for (int i = 0; i < 1000; i++)
{
pE = (PENTRY)malloc(sizeof(ENTRY));
pE->now = Now();
r = _MyMap.insert(std::make_pair(i, pE));
if (false == r.second)
{
printf("For some crazy reason its already there\n");
continue;
}
}
// OK, theres probably 1000 things in there now
printf("_MyMap now holds [%u] things\n", _MyMap.size() );
// The following seems stupid, but I don't understand how to free the memory otherwise
for (int i = 0; i < 1000; i++)
{
// first query
auto it = _MyMap.find(i);
// if malloc failed on an attempt earlier this could be NULL right?
// I've had free impls crash when given NULL, so I check.
if (it != _MyMap.end() &&
NULL != it->second)
free(it->second);
// second query
_MyMap.erase(i);
}
printf("_MyMap free'd and erased. size now [%u]\n", _MyMap.size());
return 0;
}
Questions are inline in the comments

You probably want this:
auto it = _Map.find(idUser);
if (it != _Map.end())
{
free(it->second);
_Map.erase (it);
}
But it's really not a good idea to store a raw pointer in a collection this way. You should, ideally, just store the data directly in the map rather than storing a pointer to it. Otherwise, use std::unique_ptr so that the destruction of the pointer automatically frees the data.

Related

Remove the warning C6001

I am using VS2017 and do not understand why I am getting compiler "Warning C6001 Using uninitialized memory 'values'", on line if(values!= NULL) in catch block.
#include <windows.h>
typedef enum
{
VALUE_STATE_NOT_AVAILABLE = 1,
VALUE_STATE_ERROR = 2,
VALUE_STATE_VALID = 3,
VALUE_STATE_UNKNOWN = 4
} XyzValueState_t;
class XyzValue
{
private: XyzValueState_t _valueState;
protected: XyzValue( XyzValueState_t valueState ) {
_valueState = valueState;
}
}
typedef XyzValue* xyzValuePtr_t;
main(){
bool flag=true;
xyzValuePtr_t* values = NULL;
unsigned int _argument=2;
if(flag==true) {
values = new PCLValuePtr_t[2]{ NULL,NULL };
try {
values[0] = new PCLUnsignedInteger(_argument);
values[1] = new PCLUnsignedInteger(_argument);
xyz(values); // passing the value to third party function which returns void
}
catch(...) {
if(values!= NULL){
for(int k = 0; k < 1; k++) {
delete values[k];
values[k] = NULL;
}
delete [] values;
values = NULL;
}
}
}
}
Thank you in advance for your help and guidance
not quite sure why your compiler thinks this might be unitialized.
But, in C++, I'd argue that the way you're building your array with new is unnecessarily complicated and error prone. This look like someone from 1993 tried to write C++11. You have initializer lists, but you don't use RAII!
so, do the C++ thing and use C++'s deterministic object lifetime to manage memory. For an array of objects, this is elegantly handled by std::vector:
#include <vector>
class XyzValue;
main(){
bool flag=true;
unsigned int _argument=2;
if(flag==true) {
std::vector<XyzValue> values(2); // default initialization for two XyzValues.
try {
xyz(values.data()); // if you need the raw contiguous memory. **You probably don't.**
}
catch(...) {
// all the manual deletion not necessary anymore, because at end of scope, things are deconstructed automatically, so this catch clause now is empty.
}
}
}
See how this is much shorter, better readable, has the same functionality, but none of the need to manually delete anything? That's why we write C++ instead of C.

My vector works sometimes and othertimes it doesn't

I'm trying to make my own vector, but i've got the following problem: When I push_back 100 times there's no problem. When I push_back 1000 the program does not work
#include <iostream>
#include <stdlib.h>
#include <conio.h>
struct Exception {
static const char* out_of_range;
};
const char* Exception::out_of_range = "[Error]: Out of range";
template < typename T >
struct vector {
typedef T myType;
public:
vector() {
m_vector = (myType*) malloc ( sizeof( myType ) );
m_position = 0;
}
template < typename ... Ts >
vector(myType head, Ts ... tail) {
m_position = 0;
m_vector = (myType*) malloc( (sizeof ...( tail ) + 1) * sizeof( myType ) );
this->push_back(head);
(this->push_back(tail),...);
}
~vector() {
free(m_vector);
m_vector = NULL;
}
void push_back( myType value ) {
m_vector[ m_position ] = value;
++m_position;
m_vector = (myType*) realloc(m_vector, m_position * sizeof(myType));
}
void pop_back() {
--m_position;
m_vector = (myType*)realloc( m_vector, m_position * sizeof (myType) );
}
myType at( size_t pos ) {
try {
if (pos < m_position)
return m_vector[ pos ];
else throw Exception::out_of_range;
} catch (const char* e) {
printf("%s", e);
return (myType){};
}
}
inline myType& front() { return *m_vector; }
inline myType& back() { return *(m_vector + size() -1); }
inline myType* data() { return m_vector; }
inline myType* begin() { return m_vector; }
inline myType* end() { return (m_vector + size()); }
inline myType operator[](size_t pos) { return m_vector[ pos ]; }
inline size_t size() { return m_position; }
inline bool empty () { return (begin() == end()? true:false); }
private:
myType* m_vector;
size_t m_position;
};
Here is my main that use push_back by 100 times:
int main() {
vector<int> v;
for(int i = 0; i < 100; ++i) v.push_back(i);
for(int i = 0; i < 100; ++i) std::cout << v[i];
}
And here the hunted code ahah:
int main() {
vector<int> v;
for(int i = 0; i < 1000; ++i) v.push_back(i);
for(int i = 0; i < 1000; ++i) std::cout << v[i];
}
With "doesn't work" I'm trying to say that when I have 100 values inserted by push_back the program show me all the values from 0 to 99... but when I've got 1000 values (I don't know why) the program show only a black screen and nothing more
Consider the first call of
void push_back(myType value) {
m_vector[m_position] = value; // Store into 0
++m_position; // set `m_position` to 1
m_vector = (myType*)realloc(m_vector, m_position * sizeof(myType)); // Allocate more space.
}
How much more space is allocated on that last line? m_position * sizeof(myType). This resolves to 1 * sizeof(myType). Enough space for 1 myType. In other words the same amount of space the program already had. This is not useful.
Let's look at the next push_back
void push_back(myType value) {
m_vector[m_position] = value; // Store into 1. There is no 1. Program now broken
++m_position; // set `m_position` to 2
m_vector = (myType*)realloc(m_vector, m_position * sizeof(myType)); // Allocate more space.
}
The next push_back writes into invalid storage. Program now officially broken and no further point debugging.
How do we fix this?
Let's ignore the fact that malloc and family don't handle complex data structures and vector does not observe the Rules of Three and Five. Those are best handled in other questions. How do we fix this with realloc?
m_vector = (myType*) realloc(m_vector, (m_position +1) * sizeof(myType));
smooths over the immediate rough spot. But this is inefficient as hell. Every addition triggers a realloc. This really, really hurts performance. Aggregate O(1) goes right out the window replaced by O(n), copy every time, plus a potentially very expensive memory allocation.1
Worse, what happens when you remove an item? You lose track of how much was in the vector and may find yourself reallocing smaller buffers. Yuck.
To do this right, first add a m_capacity member to track how much data can be stored so that we don't have to reallocate if the amount needed is less than the amount required.
Then we test for amount of space and possibly reallocate before trying to store.
void push_back( myType value ) {
if (m_position >= m_capacity)
{ // need to reallocate
m_capacity *= 2;
myType * temp = (myType*) realloc(m_vector, m_capacity *sizeof(myType));
// ask for more than is needed. Reduce number of reallocations needed
// do not overwrite m_vector. realloc can fail to allocate and then where are you?
if (temp != NULL)
{
m_vector = temp;
}
else
{
// handle error. Probably throw exception. Definitely exit function
// before trying to add new element
}
}
m_vector[ m_position ] = value; // now guarantied to have space.
++m_position;
}
1This isn't strictly true. One of the things you'll find is that memory provided often isn't as granular as what you asked for. When the program asks for X bytes, it might get a convenient block of free memory larger than X bytes. You ever noticed that sometimes you can run off the end of a buffer and the program doesn't notice and immediately crash? This extra space is one of the reasons. Quite often realloc can take advantage of this and keep using the same allocation over and over, allowing the program to legally see more of it. You can't count on this, though.
I assume the idea behind your code is that m_vector should always be able to hold one more value than it currently does. Your push_back funtion is wrong then, it should realloc for m_position + 1.

Segmentation fault due to size() function of self-implemented data structure in C++

I am using a vector of vector in my A3 code. I sort the vector of vector's at insertion. I store my keys in the 0th index of each sub vector.
In my size method, I am trying to use the direct call for checking the size. The code below outlines my attempt. However, I get a segmentation fault on execution. Can anyone help me understand the reason for the same?
vector<vector<int>> pairs; //sorted in the insert method
int size(int key) const {
if( pairs[key].size() == 0 ) { return -1; }
else { return pairs[key].size() - 1; }
}
I have implemented the same successfully previously, however, it was a very inefficient solution using linear search. Here is the code for the same:
int size(int key) const
{
for( int i=0; i<pairs.size(); i++)
{
if( pairs[i][0] == key )
{
return pairs[i].size() - 1;
}
}
return -1;
}
This code is not enough to tell you what is happening, we can only make a guess.
I would say that your leak comes from the method data: you create a copy of the data and then return a pointer to this copy. It would be better to return an unique_ptr, so the memory is released automatically.
If you cannot change the definition of the method, then you could change the body of the method by this one:
int length = size(key);
if( length == -1 )
return nullptr;
for( int i=0; i<pairs.size(); i++)
{
if( pairs[i][0] == key )
{
return &pairs[i][1];
}
}
return nullptr;

Deleting objects on the heap which store data on the heap

My program has been written using classes from the SDL library.
I have the following class:
class s_group
{
private:
SDL_Surface* image;
unsigned int* F_total;
float* F_length;
SDL_Rect** F;
float* F_current;
unsigned int S_total;
unsigned int S_current;
public:
s_group(void);
virtual ~s_group(void);
bool setup( const char* filename, unsigned int s );
//other member functions
};
Private member pointers each store the location of memory declared on the heap, as allocated by the member function setup.
bool s_group::setup( const char* filename, unsigned int s )
{
s_group::~s_group();//delete already allocated heap memory
if(!load_file(image, filename))
{
image = NULL;
return false;
}
S_total = s;
F = new SDL_Rect*[S_total];
F_total = new unsigned int[S_total];
F_length = new float[S_total];
F_current = new float[S_total];
for(unsigned int index = 0; index < S_total; ++index)
{
F[index] = NULL;
F_total[index] = 0;
F_length[index] = 0.f;
F_current[index] = 0.f;
}
//loop for each array slot and set values of data
return true;
}
Within a large function I create an object of this class on the heap, storing its address in an s_group pointer named sparkle.
s_group* sparkle = new s_group;
sparkle->setup("sparkle_final.png", 1 );
On completion of the function I call delete to reallocate the heap memory. Removing this line solves the problem, however there would then be a memory leak.
delete sparkle;
sparkle = NULL;
This will call the destructor of the class which is where I believe the error occurs due to an internal use of the delete operator.
s_group::~s_group(void)
{
SDL_FreeSurface(image);
image = NULL;
for(unsigned int s = 0; s < S_total; ++s)
{
for(unsigned int f = 0; f < F_total[s]; ++f)
{
F[s][f].x = 0;
F[s][f].y = 0;
F[s][f].w = 0;
F[s][f].h = 0;
}
delete[] F[s];
F[s] = NULL;
}
delete[] F;
F = NULL;
delete[] F_total;
F_total = NULL;
delete[] F_length;
F_length = NULL;
delete[] F_current;
F_current = NULL;
S_total = 0;
S_current = 0;
}
On reaching the delete operator, a dialog box appears stating:
Windows has triggered a breakpoint in Program.exe. This may be due to a corruption of the heap, which indicates a bug in Program.exe or any of the DLLs it has loaded.
How do I delete this object without causing the heap corruption?
From effective C++ Scott Meyers
Item 9: Never call virtual functions during construction or destruction.
You shouldn't call virtual functions during construction or destruction, because the calls won't do what you think, and if they did, you'd still be unhappy. If you're a recovering Java or C# programmer, pay close attention to this Item, because this is a place where those languages zig, while C++ zags.
Actually, even though you should define your destructor, calling it forcibly should be out of the question
I'm unable to compile your code but here goes..
The first thing I noticed was that you called your destructor.. You don't want to do that! Instead, create a release function and call that.
The next thing I noticed is that there is no FRAME variable within the class itself.. so this line:
FRAME = new SDL_Rect*[S_total];
is going to cause a compilation error and your destructor uses FRAME but no such variable exists. I think you meant to change it to F because if not, then this line:
F[index] = NULL;
is undefined behaviour since F is uninitialized..
Also, you never initialized each index of FRAME and so accessing it in the destructor like:
FRAME[s][f].x = 0;
is a no-no.
Again, you call
delete[] F;
F = NULL;
but F has no memory allocated and is uninitialized.
Thus with all the patches I think:
class s_group
{
private:
SDL_Surface* image;
unsigned int* F_total;
float* F_length;
SDL_Rect** FRAME;
float* F_current;
unsigned int S_total;
unsigned int S_current;
void Release();
public:
s_group(void);
virtual ~s_group(void);
bool setup(const char* filename, unsigned int s);
//other member functions
};
bool s_group::setup(const char* filename, unsigned int s)
{
Release();//delete already allocated heap memory
if(!load_file(image, filename))
{
image = NULL;
return false;
}
S_total = s;
FRAME = new SDL_Rect*[S_total];
F_total = new unsigned int[S_total];
F_length = new float[S_total];
F_current = new float[S_total];
for(unsigned int index = 0; index < S_total; ++index)
{
FRAME[index] = NULL;
F_total[index] = 0;
F_length[index] = 0.f;
F_current[index] = 0.f;
}
//loop for each array slot and set values of data
return true;
}
void s_group::Release()
{
SDL_FreeSurface(image);
image = NULL;
for(unsigned int s = 0; s < S_total; ++s)
{
for(unsigned int f = 0; f < F_total[s]; ++f)
{
if (FRAME[s])
{
FRAME[s][f].x = 0;
FRAME[s][f].y = 0;
FRAME[s][f].w = 0;
FRAME[s][f].h = 0;
}
}
delete[] FRAME[s];
FRAME[s] = NULL;
}
delete[] FRAME;
FRAME = NULL;
delete[] F_total;
F_total = NULL;
delete[] F_length;
F_length = NULL;
delete[] F_current;
F_current = NULL;
S_total = 0;
S_current = 0;
}
s_group::~s_group(void)
{
Release();
}
should do it.. Just don't forget to allocate memory for FRAME[index] I wasn't sure how much or what you wanted to allocate so I changed the Release function to check if FRAME[index] is valid with an if-statement
I would strongly advise that you use some SmartPointers and forget about handling every single memory allocation yourself..
Since posting this question I have located the source of the error and solved the issue.
In a separate section of code which set the data values for the dynamic 2D array the loop validation was incorrect.
for( unsigned int index = 0; index <= F_total[ S_current ]; ++index ) {
//set data values for each slot in the array
F[ S_current ][ index ].x = 0; etc...
}
As can be seen the loop will clearly attempt to modify a location equal to the size of the created array. Noting of course that arrays begin at index 0, so the final slot will be at size - 1. Something very silly that I missed when writing the code. Actual loop:
for( unsigned int index = 0; index < F_total[ S_current ]; ++index ) {
//set data values for each slot in the array
F[ S_current ][ index ].x = 0; etc...
}
A message for anyone attempting their own memory management:
Finding the source of heap corruption is difficult as the compiler will locate the error in sections of code which do not necessarily cause the problem.
The cause of the problem will only ever be in the section of your code which is affecting the memory. Ensure that you do not attempt to access or worse modify any memory that you have not been given.
I still believe that memory management is a great way to learn and would rather complete any projects in this way than using containers or smart pointers as recommended. This is my personal preference despite custom memory management often offering very few advantages, only complexities.
When asking for assistance provide all related code on the problem. Although the compiler may direct you to the problem in one section, as I said before, with heap corruption it's not necessarily there.

Set pointer to element in vector to null, then check whether pointer is null (C++)

I would like to set pointers to some elements in my vector array to NULL (based on a criteria), and then check whether an element pointer is NULL. If the pointer pointing that element is NULL, I remove the element from my vector array.
My compiler is giving me an error, saying that the address expression must be an lvalue or function designator and I do not understand why (line location commented in code). Since I am taking the address of the value using &, am I not seeing if the pointer pointing to that element is NULL?
I included the preceding code as the error may lie there,
Relevant code:
vector<particle> pl = c.particlelist;
vector<particle> noncollision = c.particlelist;
vector<vector<particle>> collisionlist = new vector<vector<particle>>();
for (int i = 0; i < c.numparticles-1; i++){
particle first = pl[i];
for (int j = i+1; j < c.numparticles; j++)
{
particle second = pl[j];
double d = distance(first, second);
if (d==0)
{
vector<particle> temp = {pl[i], pl[j]};
collisionlist.push_back(temp);
noncollision[i].setxposint(NULL);
noncollision[j].setxposint(NULL);
}
else
{
}
}
}
int j = 0;
for (int i = 0; i < noncollision.size(); i++)
{
if (&(noncollision[i].getxpos()) == NULL) ////// ERROR HERE
{
noncollision.erase(noncollision.begin()+i);
}
else
{
j++;
}
}
I am new to C++, and if you could suggest a more elegant way to do this, or a fix, it would be much appreciated. I also assume that my method of setting the pointer to an element, noncollision[i].setxposint(NULL); is correct? Can I return an integer using a function, and take the address?
Functions for getxpos and setxposint:
int particle::getxpos(){
return xpos;
}
void particle::setxposint(int b){
xpos = b;
}
You're using & to take a pointer to a temporary vale (the return from getxpos) which isn't allowed; since a temporary will be going away, the address won't be useful in any way so the language doesn't allow it. It certainly wouldn't ever be NULL even if you could get its address.
noncollision[i].setxposint(NULL);
All that line is doing is setting xpos to zero. Generally the term NULL is used with pointers, and 0 is used with things like integers. NULL is usually a macro for 0L anyway.
&(noncollision[i].getxpos()) == NULL
What this is doing, which is incorrect, is attempting to take the address of the return value from the member method getxpos() and compare it to NULL. Whereas what you really want to do is simply see if the function returns zero. So simply change this line to:
noncollision[i].getxpos() == 0
I'll explain why the compiler doesn't understand what you mean.
When you write
&(someFunction())
you are asking for the address of the thing that the function returns. But functions return values. A value doesn't have an address. Variables have addresses.
When something is a word of memory (which will contain a value), it can be used as an lvalue (left-value), because you can put things into that word of memory:
int b = 1; //make room for an `int` on the stack, then put a `1` there.
When something is just a value, it can only ever be used as an rvalue. The following would not compile, for the same reason that your code would not:
int b; //make room for an `int` on the stack.
42 = b; //ERROR, this makes no sense.
if (42 == NULL) { std::cout << "this is never true" << std::endl; }
&42; //ERROR, 42 isn't a piece of memory, it's a value.
(Caveat: you can use values to refer to words in memory: this usage is called a pointer, e.g.
int b = 1;
*((int *)(42)) = b;
meaning "put the value of b into the memory which has the address 42. This compiles fine (but crashes if you're not allowed to write to the memory at 42.)
It looks to me you're trying to keep track of 'visited' items, not sure exactly in which way.
Instead of "modifying" the items, you could use an "external" mark. A set looks to be fine here. You could use a set of iterators into the particle list, or in this case a set of indices (i,j) which will likely be more stable.
Here's a start:
#include <vector>
#include <set>
struct particle { };
double distance(particle const&, particle const&) { return 1.0; }
struct context
{
std::size_t numparticles;
std::vector<particle> particlelist;
context() : numparticles(100), particlelist(numparticles) {}
};
static context c;
int main()
{
using std::vector;
using std::size_t;
vector<particle> pl = c.particlelist;
vector<vector<particle>> collisionlist;
std::set<size_t> collision;
for(size_t i = 0; i < c.numparticles-1; i++)
{
particle first = pl[i];
for(size_t j = i+1; j < c.numparticles; j++)
{
particle second = pl[j];
double d = distance(first, second);
if(d < 0.0001)
{
collisionlist.push_back({pl[i], pl[j]});
collision.insert(i);
collision.insert(j);
}
else
{
}
}
}
for(size_t i = 0; i < pl.size(); i++)
{
if(collision.end() != collision.find(i))
{
// do something
}
}
// alternatively
for (int index : collision)
{
particle& p = pl[index];
// do something
}
}
NOTE Be very very wary of floating point comparison like
if (d==0.0) // uhoh
because it will likely not do what you expect
How dangerous is it to compare floating point values?
What is the most effective way for float and double comparison?
Is floating-point == ever OK?
It seems that you are trying to check pairs of points for collisions. You then record for each point whether it has any collision. This is best handled by a simple list of flags:
std::vector<bool> has_collision(c.numparticles, false); // init: no collisions found
Afterwards:
if (d==0)
{
has_collision[i] = true;
has_collision[j] = true;
}
At the end, iterate over the list of flags and get the points that have no collisions:
for (size_t i = 0; i < c.numparticles; ++i)
{
if (!has_collision[i])
{
// whatever
// possibly push_back pl[i] into some list
}
}
In addition: using a vector to hold a pair (i,j) of points is confusing. Standard library has the std::pair type for purposes such as this.
Also: you don't need explicit dynamic allocation (new); let Standard Library manage memory for you in a safe, non-confusing way. Instead of
vector<vector<particle>> collisionlist = *new vector<vector<particle>>();
Use
vector<vector<particle>> collisionlist;
(or vector<pair<particle, particle>>, as described above).