I went to a job interview today and was given this interesting question.
Besides the memory leak and the fact there is no virtual dtor, why does this code crash?
#include <iostream>
//besides the obvious mem leak, why does this code crash?
class Shape
{
public:
virtual void draw() const = 0;
};
class Circle : public Shape
{
public:
virtual void draw() const { }
int radius;
};
class Rectangle : public Shape
{
public:
virtual void draw() const { }
int height;
int width;
};
int main()
{
Shape * shapes = new Rectangle[10];
for (int i = 0; i < 10; ++i)
shapes[i].draw();
}
You cannot index like that. You have allocated an array of Rectangles and stored a pointer to the first in shapes. When you do shapes[1] you're dereferencing (shapes + 1). This will not give you a pointer to the next Rectangle, but a pointer to what would be the next Shape in a presumed array of Shape. Of course, this is undefined behaviour. In your case, you're being lucky and getting a crash.
Using a pointer to Rectangle makes the indexing work correctly.
int main()
{
Rectangle * shapes = new Rectangle[10];
for (int i = 0; i < 10; ++i) shapes[i].draw();
}
If you want to have different kinds of Shapes in the array and use them polymorphically you need an array of pointers to Shape.
As Martinho Fernandes said, the indexing is wrong. If you wanted instead to store an array of Shapes, you would have to do so using an array of Shape *'s, like so:
int main()
{
Shape ** shapes = new Shape*[10];
for (int i = 0; i < 10; ++i) shapes[i] = new Rectangle;
for (int i = 0; i < 10; ++i) shapes[i]->draw();
}
Note that you have to do an extra step of initializing the Rectangle, since initializing the array only sets up the pointers, and not the objects themselves.
When indexing a pointer, the compiler will add the appropriate amount based on the size of what's located inside the array. So say that sizeof(Shape) = 4 (as it has no member variables). But sizeof(Rectangle) = 12 (exact numbers are likely wrong).
So when you index starting at say... 0x0 for the first element, then when you try to access the 10th element you're trying to go to an invalid address or a location that's not the beginning of the object.
Related
I have these kind of classes:
Game:
class Game {
private:
BoardField*** m_board_fields;
public:
Game() {
m_board_fields = new BoardField**[8];
for (int i = 0; i < 8; i++) {
m_board_fields[i] = new BoardField*[8];
}
}
Game::~Game() {
for (int i = 0; i < 8; i++) {
for (int j = 0; i < 8; j++) {
delete m_board_fields[i][j];
}
delete[] m_board_fields[i];
}
delete[] m_board_fields;
}
}
BoardField:
class BoardField {
private:
ChessPiece* m_piece;
....
public:
BoardField::~BoardField() {
delete m_piece;
}
}
And on the close of the program I get error in ~BordField:
Exception thrown: read access violation.
this was 0xFDFDFDFD.
Did I made my destructors incorrect? What is the best way to clear memory from multidimensional array ?
There is are two fundamental flaws in your design:
there is no clear ownership of the BoardFields: someone create it, someone else deletes it. It can work if you're very cautious but it's error prone.
you do not ensure the rule of 3 (or better 5): if you have any piece of code where you create a copy of either your Game or a of any BoardField the first object that gets destroyed will delete the m_piece pointer, and when the second object gets destroyed, it'll try to delete a second time the same pointer, which is UB.
There is a third important issue: you're over-using raw pointers:
if m_board_fields is a 2d array of fixed size, make it a fixed size array (aka BoardField* m_board_fields[8][8]). If you want to keep its size dynamic, use vectors.
a cell of m_board_field could be a pointer if there's some polymorphism expected. But this seems not the case here, as obviously ChessPiece is the polymorphic class. So better use plain fields instead of pointers (aka BoardField m_board_fields[8][8]).
Finally, instead of using raw pointer to ChessPiece, better use a shared_ptr<ChessPiece> : you don't have to worry about shallow pointer copies and double delete; the shared_ptr will take care of itself and destroy the object if it's no longer used.
class tile :public RectangleShape
{
public:
int w;
int t1rgb1;
int t1rgb2;
int t1rgb3;
int t2rgb1;
int t2rgb2;
int t2rgb3;
void modify(int,int,int,int,int,int,int);
};
I have a tile class that inherits RectangleShape. I've made a 2d Vector of this class and want to push_back Rectangle shapes into it from a method of another class. I know my code won't work because I don't know where my RectangleShape will be push_back'ed into, x or y.
board::create(int x, int y){
cBoard = vector <vector <tile> >(x, vector< tile >(y, tile()));
int counter = 0;
RectangleShape t;
for(int i = 0; i < y; i++){
counter = 0;
if(i % 2 == 1){
counter = 1;
}
for(int ii = 0; ii < x; ii++){
if(counter % 2 == 0){
t.setFillColor(Color::Red);
cBoard.push_back(t);
cout << "red";
counter++;
}
else if(counter % 2 == 1){
t.setFillColor(Color::Green);
cBoard.push_back(t);
cout << "green";
counter++;
}
}
cout << endl;
}
}
The short answer is that you can't. Changing it to a 1D vector won't help either.
If you want to combine a container with inheritance, you almost certainly need the container to store some sort of pointer-like or reference-like thing, rather than storing the objects directly.
Depending on the situation, those might be std::unique_ptr, or std::reference_wrapper, or possibly just raw pointers in something like a Boost ptr_vector. One way or another, however, if you're using inheritance, you just about need to deal with the objects via something pointer-like or something reference-like rather than working directly with objects themselves.
The way to do this kind of thing is using dynamic_cast and store pointers, rather than values. For example:
RectangleShape r1 = new RectangleShape();
RectangleShape r2 = new tile();
tile* t1 = dynamic_cast<tile>(r1);
tile* t2 = dynamic_cast<tile>(r2);
In the above code snippet, t1 will be nullptr, because r1 is not a tile object. t2 will point to the correct tile object. Storing the pointers in a vector should probably be done with unique_ptr to prevent memory management issues.
If this is not what you want to do, if you want to actually create a tile object out of a RectangleShape object, then you would need to give the tile class a constructor that takes a RectangleShape object (preferably explicit), or create a function that takes a RectangleShape object and returns a tile object.
Finally, make sure when you're doing this that RectangleShape is actually the kind of object you would want to derive another class from. It must have a virtual destructor, and any overriden methods should also be virtual.
I am just starting to really understand Polymorphism, but still this is a new topic for me.
So here is my Problem: I have to classes, enemy and Bankrobber. However Bankrobber inherits from
enemy. I tried to make an array of 10 Bankrobbers. A global function should then use all members of the array to do something, well I guess this is a worthless description, so here is the code:
void UpdateEnemies(Enemy * p_Enemy, int counter) {
for(unsigned int i = 0;i < counter;i++) {
p_Enemy[i].Update();
}
}
int main(void) {
BankRobber EnemyArray[10];
Enemy * p_Enemy = new BankRobber(13,1);
UpdateEnemies(EnemyArray,10);
system("PAUSE");
};
I apologize for any language mistakes. I am not a native speaker
My actual Problem: This code is just for practicing, so the purpose is just to see 10 times Update on the console, for each member of the Array. So the function UpdateEnemys should call all the enemy.update functions. The method with the type casting is not exactly what I want, cause it is not dynamicly anymore, as there will be more enemy later on. Not only Bankrobbers.
Polymorphism only works on single objects, accessed by a reference or pointer to a base class. It does not work on an array of objects: to access array elements, the element size must be known, and that's not the case if you have a pointer to a base class.
You would need an extra level of indirection: an array of pointers to single objects, along the lines of
void UpdateEnemies(Enemy ** p_Enemy, int counter) {
for(unsigned int i = 0;i < counter;i++) {
p_Enemy[i]->Update();
}
}
int main() {
// An array of Enemy base-class pointers
Enemy * EnemyArray[10];
// Populate with pointers to concrete Enemy types
for (unsigned i = 0; i < 9; ++i) {
EnemyArray[i] = new BankRobber;
}
// Of course, the array can contain pointers to different Enemy types
EnemyArray[9] = new Dragon;
// The function can act polymorphically on these
UpdateEnemies(EnemyArray,10);
// Don't forget to delete them. Enemy must have a virtual destructor.
for (unsigned i = 0; i < 10; ++i) {
delete EnemyArray[i];
}
}
You should also consider using RAII types, such as containers and smart pointers, to manage these dynamic resources; but that's beyond the scope of this question.
Declaring an array of BankRobber like this
BankRobber EnemyArray[10];
But than acessing them through the base class pointer like this
Enemy * p_Enemy;
p_Enemy[i].Update();
Wouldn't work. That's because indexing an array p_Enemy[i] will be done by using the offcet sizeof(Enemy)
But sizeof(BankRobber) is probably bigger than from sizeof(Enemy), so p_Enemy[i] will end up in the wrong place
You should use a vector of pointers instead, like
std::vector<Enemy*>
That way you can also use polymorphism if you add pointers to different objects into the vector. And you don't need to pass the ugly int counter around
Indeed you didn't say exactly what is the problem.
Did you try casting inside your code? Something like:
void UpdateEnemies(Enemy * p_Enemy, int counter) {
BankRobber *pRobber = (BankRobber*)p_Enemy;
for(unsigned int i = 0;i < counter;i++) {
pRobber[i].Update();
}
}
I have a GameObject which contains an array of Shapes(assigned via malloc). Shapes have a list of Points in them and can be inherited to be Polygons.
Init code:
GameObject g1(true, true);
Color c(0, 0, 1, 0);
Point p(100, 100, 0);
Polygon s(p, c);
s.addPoint(p);
s.createRegularShape(4, 50.0f);
g1.addShape(s);
This is in the header.
Shape* shapes;
This is where it breaks (when I try to access the data)
void GameObject::draw(unsigned int gameTime)
{
if(visible)
{
for(int i = 0; i < count; i++)
shapes[i].draw();//Access violation happens here
}
}
This is how I add the Shape to the Shape array.
void GameObject::addShape(Shape const& shape)
{
if(count == size)
{
size += 4;
shapes = (Shape*)realloc(shapes, sizeof(Shape) * size);
}
shapes[count] = shape;
count++;
}
This is where I allocate memory for the Shape. This is called in the constructor when we need to allocate memory to the shapes array.
void GameObject::clearShapes(int size)
{
if(count > 0)
free(shapes);
shapes = (Shape*)malloc(sizeof(Shape) * size);
count = 0;
GameObject::size = size;
}
So basically, what am I doing wrong? How am I getting an access violation from this code? The data seems to all be the correct size and be legitimate.
When you use malloc(), the constructor of the objects is not run. As you can guess this can create all sorts of problems. Use new instead.
Do not use malloc() in C++ to create objects.
This:
Shape* shapes;
is an array of Shape objects, not an array of Shape pointers. That means the initial contents:
shapes = (Shape*)malloc(sizeof(Shape) * size);
and later:
shapes = (Shape*)realloc(shapes, sizeof(Shape) * size);
are not constructed. So when you later do:
shapes[count] = shape;
The assignment operator is called on shapes[count], which is a non-constructed Shape. It looks to me like you're waaay into undefined behavior here. Any kind of runtime error is possible.
Get rid of malloc() and realloc(), and instead use an std::vector<Shape> where you push_back() new Shapes. If you want to keep doing it with a plain dynamic array, then you should switch to an array of pointers instead:
Shape** shapes;
And only hold Shape pointers in there. This of course requires refactoring of your program logic, and I don't see why you would want to keep using malloc() and realloc().
I have a class called Foo which has a member that is a pointer to a vector of pointers to another class called Bar. I initialise it in the constructor but I'm not sure how to deallocate it in the destructor. I'm still learning. Would appreciate your help. The reason for having this member is so that the scope persists beyond that method i.e. beyond the stack. Thanks.
#include <iostream>
#include <vector>
using namespace std;
class Bar {};
class Foo {
public:
Foo() {
bars = new vector<Bar*>*[10];
for (int i = 0; i < 10; i++) {
bars[i]->push_back(new Bar());
}
}
~Foo () {
for (int i = 0; i < 10; i++) {
// TODO: how to clean up bars properly?
}
}
private:
vector<Bar*>** bars;
};
int main () {
new Foo();
return 0;
}
Update: I appreciate the feedback on all fronts. I'm new to C and C++. Basically I wanted a 2d structure as a class member that would persist for the lifetime of the class. The reason the outer structure is an array is because I know how big it needs to be. Otherwise I was previously using vector of vectors.
This isn't even allocated properly. You allocate an array of pointers to std::vector<Bar*>, but never any std::Vector<Bar*>.
The best thing to do is just something like std::vector<std::unique_ptr<Bar>> or even std::unique_ptr<std::vector<std::unique_ptr<Bar>>> or something like that. What you've got is just WTF.
Or std::unique_ptr<std::array<std::unique_ptr<std::vector<std::unique_ptr<Bar>>>, 10>>.This is an exact match (but self-cleaning).
The number of pointers is a bit ridiculous, as all they are doing is causing confusion and leaks, as evident from non-proper initialization and the question's title. You don't actually need any pointers at all, and don't have to worry about any cleanup.
For a 2D array with the first dimension passed into the constructor, you can use a vector of vectors:
std::vector<std::vector<Bar>> bars;
To initialize the outer vector with the passed in size, use an initializer:
Foo(size_t size)
: bars(size) {}
When the object is destroyed, bars and all of it elements are as well, so there's no chance of forgetting to clean up or doing so improperly.
If performance is an issue, this can be translated into a sort of Matrix2D class that acts like a 2D array, but really only has an underlying 1D array.
EDIT: In the case of a 2D structure (and you said you know how big your 2D structure needs to be, so we'll assume that the 10 in your loops is the size of the 2D array you desire.
#include <iostream>
#include <vector>
using namespace std;
class Bar {
public:
int BarInfo;
};
class Foo {
public:
Foo() {
// Allocates 10 vector spots for 10 bar elements - 100 bars, 10 x 10
for (int i = 0; i < 10; i++) {
// Puts 10 bars pointer at the end;
// Heap-allocated (dynamically), which
// means it survives until you delete it
// The [10] is array syntax, meaning you'll have 10 bars
// for each bars[index] and then
// you can access it by bars[index][0-9]
// If you need it to be more dynamic
// then you should try vector<vector<Bar>>
bars.push_back(new Bar[10]);
}
}
Bar* operator[] (int index) {
return bars[index];
}
~Foo () {
// Cleanup, because you have pointers inside the vector,
// Must be done one at a time for each element
for (int i = 0; i < bars.size(); i++) {
// TODO: how to clean up bars properly?
// Each spot in the vector<> contains 10 bars,
// so you use the array deletion
// and not just regular 'delete'
delete[] bars[i]; // deletes the 10 array elements
}
}
private:
// vector might not be a bad idea.
vector<Bar*> bars;
};
This is the main I have for testing the code written, and it works like you would think a 2D array should work:
int main ( int argc, char* argv[] ) {
Foo foo;
// Bar at 1st row, 2nd column ( row index 0, column index 1 )
// Bar& is a reference
Bar& bar12 = foo[0][1];
bar12.BarInfo = 25;
int stuffInsideBar = foo[0][1].BarInfo; // 25
return 0;
}
I hope that helps and gets you closer to what you're doing. I've used a technique here that might go over a starters head to make the Foo class behave like you would think a 2D array would. It's called operator overloading. It's a powerful feature in C++, so once you master more basics it might be useful to you in your future projects or current one. Good luck!
~~~~~~~~~~~~~~~~~~~~~~~
OLD ANSWER BEFORE EDIT
~~~~~~~~~~~~~~~~~~~~~~~
It appears you're doing far too much indirection. While another person's answer shows you how to clean up what you've managed to do, I think you could benefit from changing how exactly you're handling the class.
#include <iostream>
#include <vector>
using namespace std;
class Bar {};
class Foo {
public:
Foo() : bars() {
// bars is no longer a pointer-to-vectors, so you can just
// allocate it in the constructor - see bars() after Foo()
//bars = new vector<Bar>();
for (int i = 0; i < 10; i++) {
// Puts 1 bar pointer at the end;
// Heap-allocated (dynamically), which
// means it survives until you delete it
bars.push_back(new Bar());
}
}
~Foo () {
// Cleanup, because you have pointers inside the vector,
// Must be done one at a time for each element
for (int i = 0; i < 10; i++) {
// TODO: how to clean up bars properly?
// TODOING: One at a time
delete bars[i]; // deletes pointer at i
}
}
private:
// You don't need to ** the vector<>,
// because it's inside the class and
// will survive for as long as the class does
// This vector will also be copied to copies of Foo,
// but the pointers will remain the same at the time
// of copying.
// Keep in mind, if you want to share the vector, than
// making it a std::shared_ptr of a
// vector might not be a bad idea.
vector<Bar*> bars;
};
If you pass the class by reference into functions, than the vector<Bar*> inside the class won't copy itself or delete itself, making it persist past a single stack frame.
In your main, this should clean up properly and is a lot easier to keep track of than vector** . However, if for some reason vector** is required, than home_monkey's answer should help you more.
I think there is an issue with allocation. The line
new vector <Bar*> * [10]
will give you an array of points to objects of type vector <Bar*> * and you
will need to allocate some additional memory for your vector <Bar*> type.
I've had a go,
Foo()
{
bars = new vector<Bar*>*[10]; // A.
for (int i = 0; i < 10; i++)
{
bars[i] = new vector<Bar*>; // B. Extra memory assigned here.
bars[i]->push_back(new Bar); // C.
}
}
To free resources, you'll have to reverse the above
~Foo ()
{
for (int i = 0; i < 10; i++)
{
// I'm assuming that each vector has one element
delete bars[i][0]; // Free C
delete bars[i]; // Free B
}
delete [] bars; // Free A
}
I don't believe you're even allocating it properly. To undo what you've done so far, all you'd have to do is:
for(int i=0; i < 10; ++i)
while(bars[i]->size > 0)
{
delete *bars[i]->front();
pop_front();
}
delete[] bars;
But, you need to allocate each of the vectors themselves, for instance in the constructor:
for(int i=0; i<10; ++i)
bars[i] = new vector<Bar*>();
Which would require you change the destructor to:
for(int i=0; i < 10; ++i)
{
while(bars[i]->size > 0)
{
delete *bars[i]->front();
pop_front();
}
delete bars[i];
}
delete[] bars;
With regard to your update, I would then suggest changing the type of bars to:
vector<Bar*>* bars;
and the allocation to (without the need to do the for loop allocation suggested above):
bars = new vector<Bar*>[10];