I have noticed strange behavior (IMO) on MSVC 14 Comm. in Debug x86 solution.
Code below throws Exception when vector::resize is not included.
Note: after assigment some entities may be unassigned by passing nullptr.
vector<Entity*> m_entities;
(...)
// find empty slot
u_int id = m_entities.size();
for(u_int i=0; i<m_entities.size(); ++i)
{
if(m_entities[i] == nullptr)
{
id = i;
break;
}
}
// vector realloc
if(id == m_entities.capacity())
{
u_int newSize = m_entities.capacity() * 2;
m_entities.reserve(newSize);
//m_entities.resize(newSize);
}
// assign
entity->m_id = id;
m_entities[id] = entity;
It looks like operator[] checks size() instead of capacity() - am I right?
You can NOT access the reserved area of the vector if it was not initialized. reserve does not initialize anything it just reserve (as it was named) some memory to not reallocate the vector each time a new item is pushed back
Try to run this code:
#include <iostream>
#include <string>
#include <vector>
class my_class{
public:
my_class(){
x="I am an initialized item";
}
std::string x;
};
int main()
{
std::vector<my_class> v(2);
v.reserve(3);
std::cout << v[0].x <<std::endl<< v[1].x <<std::endl <<v[2].x;
}
You may got compiling error in the debug mode(depending on your compiler), it may pass and give undefined behaviour (NOT sure about undefined behaviour please someone edit this part). In best case, it would run with printing empty string for v[2].
Live Demo
Related
I am making an array of 4 std::list. But when I try to access the array's first list's first A object and call the callMe() method on it I get a weird output.
Now 2 things could have happened:
Either the list was empty.
An A object was created when I tried to access the first element of the first list((*(arrayOflistOfA[0].begin()))).
Details of the above cases:
If no A object was created then I should have got an exception. But I didn't get any exception so I am assuming that an A object was created.
So if an A object was indeed created, then the constructor should have been called.
What am I missing?
#include <iostream>
using namespace std;
class A {
public:
A() {
cout<<"Constructor called"<<endl;
x=20;
}
void callMe();
private:
int x;
};
void A::callMe() {
cout<<"Value of x = "<<x<<endl;
}
int main() {
const int size = 4;
list<A>* arrayOflistOfA = new list<A>[size];
(*(arrayOflistOfA[0].begin())).callMe();
}
The output is:
Value of x = 0
but the output should have been:
Constructor called
Value of x = 20
If no A object was created then I should have got an exception.
Not true.
But I didn't get any exception so I am assuming that an A object was created.
Don't assume. Find out. Go to some documentation for begin() and for iterators and discover that you do not get an exception, you get UB.
An A object was created when I tried to access the first element of the first list((*(arrayOflistOfA[0].begin()))). [And] if an A object was indeed created, then the constructor should have been called.
That's right. Clearly you have no elements in the list.
And we know that, because there is no code in your program that adds elements to the list.
Also you should not dynamically allocate containers unless you really, really need to (I've never found a need to).
You aren't actually populating the list with any values. I tested the below code and include a commented explanation.
#include <iostream>
#include <list>
using namespace std;
class A {
public:
A();
void callMe();
private:
int x = 0;
};
A::A()
{
cout << "Constructor called" << endl;
x = 20;
}
void A::callMe() {
cout << "Value of x = " << x << endl;
}
int main() {
const int size = 4;
list<A>* arrayOflistOfA = new list<A>[size];
cout << arrayOflistOfA->size() << endl; // As you can see, size is 0 here - you created a list of nulls.
for (int i = 0; i < size; i++)
{
arrayOflistOfA->push_back(A());
}
// The below code demonstrates how to loop through the array once it's populated.
list<A>::iterator it;
for (auto& a : *arrayOflistOfA)
{
a.callMe();
}
return 0;
}
I got the answer to my question. Firstly I tried to run this code on my mac with GNU C++ compiler but when I ran the same code on an iPhone simulator it crashed. So as #PaulMcKenzie mentioned, I was indeed trying to dereference an invalid iterator.
I'm working on a C++11 program, where security is important and my task is to set to 0 the used memory after erasing it.
I have an std::map mapping from int to an std::vector of pointer to class. I have the index in std::map and a pointer to the instance I would like to delete.
The following code produces the output I want, however, I'm not sure if it's good formed code (or I would say I'm not sure if this code is ok or not).
I have 2 questions.
If the following code is ok,
It can only be compiled with -fpermissive, I don't understand the compiler error message.
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
class MyClass
{
private:
int num;
public:
MyClass(int num) { this->num = num; }
int GetNum() const { return this->num; }
};
void PrintWorkingData(const std::map<int, std::vector<MyClass*>>& working_data, int idx)
{
std::cout << "working_data[" << idx << "] is an std::vector, size: " << working_data[idx].size() << ", containing the following items: " << std::endl;
for (std::vector<MyClass*>::const_iterator it = working_data[idx].begin(); it != working_data[idx].end(); it++)
{
std::cout << "(*it)->GetNum() = " << (*it)->GetNum() << std::endl;
}
}
int main()
{
MyClass* DeleteMyClass;
std::map<int, std::vector<MyClass*>> working_data;
working_data[0].push_back(new MyClass{4});
working_data[0].push_back(new MyClass{7});
working_data[1].push_back(new MyClass{11});
// the origonal code isn't like this; let's suppose
// we stored in the DeleteMyClass pointer the MyClass pointer
// that we would like to delete
working_data[1].push_back(DeleteMyClass = new MyClass{22});
working_data[1].push_back(new MyClass{33});
working_data[2].push_back(new MyClass{1000});
PrintWorkingData(working_data, 0);
PrintWorkingData(working_data, 1);
PrintWorkingData(working_data, 2);
PrintWorkingData(working_data, 3);
// so our task is to delete DeleteMyClass object from working_data[DeleteItemIndex]
// and fill with 0 where it was stored
int DeleteItemIndex = 1;
std::vector<MyClass*>::iterator pos = std::find(working_data[DeleteItemIndex].begin(), working_data[DeleteItemIndex].end(), DeleteMyClass);
if (pos == working_data[DeleteItemIndex].end())
{
std::cout << "Error: The item does not present in the working_data" << std::endl;
}
else
{
std::fill(pos, pos + 1, 0);
working_data[DeleteItemIndex].erase(pos);
delete DeleteMyClass;
std::cout << "The object successfully deleted" << std::endl;
}
PrintWorkingData(working_data, 0);
PrintWorkingData(working_data, 1);
PrintWorkingData(working_data, 2);
PrintWorkingData(working_data, 3);
return 0;
}
Setting a pointer value to nullptr doesn't change the data it points to. Erasing an element from a vector will overwrite that element with all the later ones in the vector, leaving (in this case) a second pointer in allocated memory (beyond the size of the vector) to the last element in the vector.
To erase the memory occupied by the object that DeleteMyClass points to, you'll have to handle the object destruction and memory freeing separately. This is not necessarily easy or straightforward, as there can be nuances (exception handling, array vs. non-array forms) that need to be addressed. You should also keep in mind that it is possible to inspect the memory of a running process, and view the data you're trying to erase while the object that uses it is live.
Here are several approaches that might work for you case.
One way to do this is to manually call the destructor, clear out the memory, then free it.
DeleteMyClass->~MyClass();
memset(DeleteMyClass, 0, sizeof(*DeleteMyClass));
delete (void *) DeleteMyClass;
The cast on the delete call is necessary to avoid calling the destructor, and the number of bytes to clear uses the type of DeleteMyClass, which will be incorrect if what is pointed to is a class derived from MyClass.
Another alternative is to use placement new with an already allocated memory buffer and a custom deallocator (after manually calling the destructor) to free up the memory.
A third possibility is to use custom new and delete functions, either for this specific class or globally.
I've searched endlessly on SE for a logical explanation for why this is happening. It is probably something very simple that I've overlooked, however I cannot spot it and would really appreciate some assistance with this.
Last week I implemented a class to read the output of a system call from a .ini file and then find and store the required information into custom objects that are then stored in a vector inside a Config class. It is a Singleton config class storing a unique_ptr for each instance of my custom class that is created.
The thing is, when I implemented this last week on my laptop, I had zero issues reading and writing to my member vector and was able to get it working exactly how I needed it. Since pulling to my desktop computer, this vector, and any STL container that I use as a member of my class, throws a segmentation fault when I try to do anything on it, even get it's size.
I've tried to shorten the code below to only include sections that actually use this vector. I have replaced my config with A, and custom class with T, and no matter where I try to use my member container, or any other test STL containers that I add to the class, I get a segfault.
For the record, I am using Qt with C++11.
Update: This example breaks on line 50 of c.cpp when debugging, and anywhere that tries to call the vector.
Debug points to this line in stl_vector.h
// [23.2.4.2] capacity
/** Returns the number of elements in the %vector. */
size_type
size() const _GLIBCXX_NOEXCEPT
/*-> this line */ { return size_type(this->_M_impl._M_finish - this->_M_impl._M_start); }
main.cpp
#include "c.h"
int main(int argc, char *argv[])
{
C *c = C::getInstance();
delete c;
return 0;
}
t.h - Class stores information from file
#include <string>
class T
{
public:
T();
bool Active();
std::string getA();
void setA(std::string);
private:
std::string a;
};
t.cpp
#include "t.h"
T::T()
{
}
bool T::Active()
{
if(a == "")
{
return false;
}
return true;
}
std::string T::getA()
{
return this->a;
}
void T::setA(std::string newa)
{
this->a = newa;
}
c.h - Class stores T objects and parses file for information
#include "t.h"
#include <QDebug>
#include <vector>
#include <algorithm>
#include <iostream>
#include <memory>
#include <sstream>
#include <fstream>
class C
{
public:
static C* getInstance();
private:
C();
static C* instance;
static bool init;
std::vector<std::unique_ptr<T>> t_list;
void readLines(const std::string&);
};
c.cpp
#include "c.h"
bool C::init = false;
C* C::instance = nullptr;
C::C()
{
system("echo this is a test command > a.ini");
instance->readLines("a.ini");
}
C* C::getInstance()
{
if(!init)
{
instance = new C;
init = true;
}
return instance;
}
void C::readLines(const std::string &path)
{
T* new_t;
std::ifstream file(path.c_str());
if(!file.is_open())
{
qDebug() << "Unable to open " << path.c_str();
}
std::ofstream o("test.txt");
std::string line;
while(std::getline(file, line))
{
// Split string before searching
std::stringstream ss(line);
std::string seg;
std::vector<std::string> split;
std::string left, right;
// Search patterns
size_t find_a = line.find("a");
size_t del = line.find(':');
if(find_a != std::string::npos)
{
o << "test_Size: " << t_list.size() << std::endl;
if(new_t->Active())
{
T* temp = new_t;
std::unique_ptr<T> move_t(temp);
t_list.push_back(std::move(move_t));
}
o << "test: " << t_list.size() << std::endl;
std::string n;
// Check if previous ahas any null elements
// Split string to find a
n = line.substr(line.find("a "));
n = n.substr(n.find(" ", +2));
new_t->setA(n);
}
else
{
continue;
}
}
// Add last a
T* t = new_t;
std::unique_ptr<T> move_t(t);
//t_list.push_back(std::move(move_t));
o << "a: " << t_list.back().get()->getA() << std::endl;
o << t_list.size() << std::endl;
o.close();
file.close();
}
UPDATE after code change:
I see two things now: One is that new_t in C::readlines is never initialized, so this could break when new_t->Active() is called a bit later in the function. However, I believe that the main problem you're running into is in C::C(), where it says
instance->readLines("a.ini");
At this point in the execution, C::instance is not yet initialized -- you're only just constructing the object that would later be assigned to it. Because of this, this in the readlines call is invalid, and any attempt to access object members will cause UB. This latter problem can be fixed by just calling
readLines("a.ini");
in which case the currently constructed object (that will later be instance) is used for this. I have no idea what you want to happen for the first, though, so all I can say is: If you want to have a vector<unique_ptr<T>>, you will have to create objects of type T with either new T() or (arguably preferrably) std::make_unique<T>() and put them in there.
I'll also say that this is a rather ugly way to implement a singleton in C++. I mean, singletons are never really pretty, but if you're going to do it in C++, the usual way is something like the accepted answer of C++ Singleton design pattern .
Old answer:
The problem (if it is the only one, which I cannot verify because you didn't provide an MCVE) is in the lines
T move_t = new_T;
std::unique_ptr<Adapter> ptr_t(&move_t); // <-- particularly this one
m_ts.push_back(std::move(ptr_t));
You're passing a pointer to a local object into a std::unique_ptr, but the whole purpose of std::unique_ptr is to handle objects allocated with new to avoid memory leaks. Not only will the pointer you pass into it be invalid once the scope surrounding this declaration is left, even if that weren't the case the unique_ptr would attempt to delete an object that's not on the heap at the end of its lifecycle. Both problems cause undefined behavior.
To me, it looks as though you really want to use a std::vector<T> instead of std::vector<std::unique_ptr<T>>, but that's a design issue you'll have to answer yourself.
Answering my own question here. I am trying to call a member variable from within the constructor of the object that holds it, so the vector I am trying to access is not yet instantiated and doesn't exist in memory. That is what causes the Segmentation fault to occur, I am trying to access memory that is not allocated yet, hence any call acting on any member of my C class was causing this issue.
I fixed this problem by adding a public function to the class that then calls the private readLines() function. I call that public function from the object that will take ownership of it, and since this occurs after it has been instantiated, the memory is accessible and the problem disappears.
In our code we use both stl and MFC containers. I've encountered a case where we have a CArray of objects, where each object contains an std::vector.
After adding several objects to the CArray, so that the data in the CArray will be reallocated and copied when it reaches it's maximum size, it seems like the inner vector is corrupted. When I iterate over the CArray and for each object iterate over the std::vector, I get a "vector iterator not dereferencable" error.
I looked at the MFC code and it uses memcpy() to copy the data after reallocating. In the std::vector (I use visual studio) there is member called _Myproxy which has a member called _Mycont which seems to change it's value in the new vector (the vector that was copied by memcpy()).
I replicated this issue, I'm attaching the sample code below.
I can refactor this code and I will probably do so, but I want to understand exactly what's happening.
#include "stdafx.h"
#include <vector>
#include <iostream>
// an object which holds an std::vector
class test_t
{
public:
test_t() {}
~test_t()
{
std::cout << "d'tor" << std::endl;
}
void add(int i)
{
m_vec.push_back(i);
}
void print()
{
for (std::vector<int>::iterator it = m_vec.begin(); it != m_vec.end(); ++it)
{
int i = *it;
std::cout << i << std::endl;
}
std::cout << std::endl;
}
private:
std::vector<int> m_vec;
};
void test()
{
// array if objects where each object holds an std::vector
CArray<test_t, test_t&> arr;
for (int i = 0; i < 10; ++i)
{
test_t t;
int j = arr.Add(t);
test_t& rt = arr[i];
rt.add(1);
rt.add(2);
rt.add(3);
}
for (int i = 0; i < arr.GetSize(); ++i)
{
test_t& rt = arr[i];
rt.print(); // error occurs here
}
}
Thanks,
Gabriel
CArray doesnt play well with non-POD types, relying on memcpy_s when resizing. You can make it work, but in general it's best avoided for this use case.
See the note here: https://msdn.microsoft.com/en-us/library/4h2f09ct.aspx
I am learning C++ and I am having quite a lot of trouble with my current assignment. I have completed a good amount of it so far. However I have been making very slow progress of late due to what I think is my poor understanding of what is going on behind the scenes.
What I am trying to do in the following code is:
Get two separate values (Bullet damage). Done.
Create a dynamic array. Done.
Fill a part (that is the size of a modulus of a random number between 1 and 10) of said dynamic array with one value and the rest with the other in a random order. Here I am having trouble.
Clean up the memory used by said dynamic array. Done.
The error I get is as follows:
Unhandled exception at 0x00a323e3 in Class 3.exe: 0xC0000005: Access
violation reading location 0xcdcdcdcd.
I'm pretty sure that the error occurs when I try to set ammoArray[i] to a value. But I don't know why it's giving it to me, my code compiles fine. I played around with it a bit and in one case I got it to store the memory addresses of bDamage and sDamage and then print out the memory addresses of each element of the array. What I want it to do is store the values held by bDamage and sDamage.
Now for my question:
Why won't ammoArray store the values of bDamage and sDamage instead of the memory addresses of the array's elements? And How do I get it to store them?
Here is my Main.cpp:
#include <cstdlib>
#include "Ammunition.h"
#include "AmmunitionManager.h"
#include "Bullet.h"
#include "Game.h"
#include "Pistol.h"
#include "Player.h"
#include "Point.h"
#include "Shell.h"
#include "Shotgun.h"
#include "WeaponManager.h"
#include "Weapons.h"
using namespace std;
void main()
{
Ammunition amVar;
AmmunitionManager *var = new AmmunitionManager();
amVar.setBDamage(6);
amVar.setSDamage(2);
var->FillAmmoArray(amVar.getSDamage(),amVar.getBDamage());
system("PAUSE");
}
Here is the .h file of the class in question:
#ifndef AMMUNITIONMANAGER_H
#define AMMUNITIONMANAGER_H
#include "Point.h"
#include "Ammunition.h"
class AmmunitionManager
{
public:
AmmunitionManager();
AmmunitionManager(int,int);
~AmmunitionManager();
void FillAmmoArray(int,int);
private:
Ammunition Ammo;
int **ammoArray;
};
#endif
Here is the .cpp file of the class in question:
#include <iostream>
#include <cstdlib>
#include <ctime>
#include "AmmunitionManager.h"
#include "Point.h"
#include "Ammunition.h"
using namespace std;
AmmunitionManager::AmmunitionManager()
{
}
AmmunitionManager::AmmunitionManager(int sDamage,int bDamage)
:Ammo(sDamage,bDamage)
{
cout << "Filling ammo reservoir." << endl;
ammoArray = new int* [10];
}
void AmmunitionManager::FillAmmoArray(int sDamage,int bDamage)
{
srand(time(NULL));
int *holdS = &sDamage;
int *holdB = &bDamage;
if(ammoArray)
{
for(int i = 0;i < 9;i++)
{
int randC = rand() % 2 + 1;
if(randC == 1)
{
cout << "Was: " << ammoArray[i] << endl;//I am getting the error here.
ammoArray[i] = holdS;
cout << "Is: " << ammoArray[i] << endl;
}
if(randC == 2)
{
cout << "Was: " << ammoArray[i] << endl;//I am getting the error here.
ammoArray[i] = holdB;
cout << "Is: " << ammoArray[i] << endl;
}
}
}
}
AmmunitionManager::~AmmunitionManager()
{
*ammoArray = 0;
if(ammoArray)
{
delete [] ammoArray;
}
}
Why won't ammoArray store the values of bDamage and sDamage instead of the memory addresses of the array's elements?
Because you said it should store addresses.
Here is a pointer to a pointer:
int **ammoArray;
and here is an array of pointers:
ammoArray = new int* [10];
And How do I get it to store them?
By doing this instead:
int *ammoArray;
and this:
ammoArray = new int [10];
and adjusting FillAmmoArray accordingly.
The default constructor should look like this:
AmmunitionManager::AmmunitionManager()
: ammoArray(nullptr)
{
}
The destructor should look like this:
AmmunitionManager::~AmmunitionManager()
{
delete [] ammoArray;
}
And you should only call srand once.
It's usually done at the beginning of main.
I'm not getting any errors (VS2013). But the values stored are the addresses of sDamage and bDamage.
Did you properly use AmmunitionManager(int sDamage,int bDamage) as a constructor for creating the AmmunitionManager object? From what I'm seeing, you're not.
Apart from that, may I ask why you're using exotic constructs such as **ammoArray instead of e.g. a simple vector<int>? I'm guessing it's part of your assignment, but I'm asking just to make sure I'm not missing anything.
I called the object like this:
int _tmain(int argc, _TCHAR* argv[])
{
AmmunitionManager* tc = new AmmunitionManager(5,10);
tc->FillAmmoArray(10,10);
return 0;
}
The problem is that you initialize AmmunitionManager with the default constructor:
AmmunitionManager *var = new AmmunitionManager();
In you default constructor you do nothing so ammoArray may contain any value.
It is better to initialize all the data to their default values:
AmmunitionManager::AmmunitionManager() : Ammo(), ammoArray(NULL/* or nullptr for C++11 */)
{
}
Now if you call for
var->FillAmmoArray(amVar.getSDamage(),amVar.getBDamage());
It will exit immediately since ammoArray is NULL.
Or probably you want to initialize ammoArray anyway, so the default constructor should have its initialization as well:
AmmunitionManager::AmmunitionManager() : Ammo()
{
ammoArray = new int* [10];
}
Also srand should be called only once, so better to place this code
srand(time(NULL));
in the main() or any other module which is guaranteed to be executed only once.
In the destructor, there is no need to zero *ammoArray=0, it actually puts 0 at the first element of that array (and that's it), you anyway delete it. And imagine that ammoArray is NULL, accessing *ammoArray would cause another segmentation fault.
Also there is no need to check for ammoArray beibg NULL before deleting it. The standard allows to 'delete' NULL pointers. delete will just return without doing nothing.
General note
It is better to use (safer and easier to maintain) std::vector instead of (dynamic) arrays and smart pointers instead of flat ones.
It's a bit tricky answering without building and debugging, but the first thing that strikes me are: Why are you using pointers (*) to int throughout?
Why don't you just have the array as a pointer:
int *ammoArray;
and make the other int-instances (remove the pointers - * and the address-of's (&))?
Regards