Array "breaks" when resizing - c++

Well, I have a class which is supposed to be a container for quadratic polynomials (which is a template and I'm using floats there, but that shouldn't matter much). I made it using a dynamic array, and I was supposed to overload + and - operators... Not a problem, eh? Well, it seemed all nice and dandy until I actually run it.
listf listf::operator+(listf rhs)
{
listf newlist;
for(int i = 0; i < elementcount; ++i)
newlist.add(array[i]);
for(int j = 0; j < rhs.elementcount; ++j)
newlist.add(rhs.array[j]);
std::cout<<newlist;
return newlist;
}
Nothing much. Should do its job correctly, right? That cout is just to check if it works. But it does not.
Should do something like this, right?
With one list consisting of:
X^2+5x+52.4
2X^2+7x-12
and the second one having just X^2+2X+1, it should make a list and display:
X^2+5x+52.4
2X^2+7x-12
X^2+2X+1
Buuuut no, it comes to this:
-1.5584e+038X^2-1.5584e+038x-1.5584e+038
-1.5584e+038X^2-1.5584e+038x-1.5584e+038
-1.5584e+038X^2-1.5584e+038x-1.5584e+038
I've been battling with it for quite some time and have not found why it would do that.
Code for adding new polynomials is still quite simple:
void listf::add(polynomial<float> plnm)
{
if(array == NULL)
{
++elementcount;
array = new polynomial<float>[elementcount];
array[0] = plnm;
}
else
{
array = resize(array, elementcount+1, elementcount);
array[elementcount++] = plnm;
}
}
And resize is a private function in this class:
polynomial<float>* listf::resize(polynomial<float>* arr, int newSize, int oldSize)
{
polynomial<float>* newArr = new polynomial<float>[newSize];
for(int i = 0; i < oldSize; ++i)
{
newArr[i] = arr[i];
}
delete[] arr;
return newArr;
}
If we're making a smaller array (for deleting objects), I just put oldSize equal to newSize (I know it's a bad practice and confusing for others, but I was just testing things :( )
I'm out of ideas. Adding new elements to an object seems working, but when I want to add two objects it breaks, prints elements that are not correct and then crashes with CodeLite reporting something like "ntdll!LdrVerifyImageMatchesChecksumEx" in Call Stack. Even better, when I tested it right now, it displayed correct values, but still crashed at return.

Forget the home-made dynamic array and use vector. Whenever you go into the realm of classes and memory management, it isn't as trivial as coding up a few new[] and delete[] calls. It can stop you dead in your tracks in the development of your program.
#include <vector>
//...
typedef std::vector<polynomial<float> > PolynomialFloatArray;
//...
class listf
{
PolynomialFloatArray array;
//...
void add(const polynomial<float>& plnm);
//...
PolynomialFloatArray& resize(PolynomialFloatArray& arr, int newSize)
};
//...
void listf::add(const polynomial<float>& plnm)
{
array.push_back(plnm);
}
PolynomialFloatArray& listf::resize(PolynomialFloatArray& arr, int newSize)
{
arr.resize(newSize);
return arr;
}
There in a nutshell is all of that code you wrote, reduced down to 2 or 3 lines.

Like the comments on the question point out, you would probably be better off using std::vector for this, as it has push_back() to add stuff to the end, and automatically resizes itself to do so, though you can force it to resize with resize().

Related

CAtlArray strange behavior using SetCount

I am having a strange issue with a CAtlArray. It works as expected if I use the Add function to add an element to the array. However, if I use SetCount before adding any elements, the program crashes. Strangely, it only works if I add elements directly with the [] operator (I know I know, the documentation says to only use [] to get an element, not to set one). I have been checking that SetCount returns true and it does.
Unfortunately, I can't get much debug info easily because this is a dll hooking another process. I can only debug by printing ...
I am wondering if this is typical behavior/if I am missing something (the documentation sucks, google did not return any helpful results, and the ATL code is hard for me to read/follow). My first thought was that SetCount(X) might have some behavior like calling Add() X times and shouldn't be called unless it is expanding the array, but SetAt doesn't work with SetCount either.
Any ideas about what might be going on here?
EDIT:
CAtlArray<MyClass*> arr;
...
size_t initialCount = 10;
if ( arr.SetCount(initialCount) ) {
for ( int i = 0; i < initialCount; i++ ) {
//arr.Add( new MyClass );//Does NOT work
//arr.SetAt( i, new MyClass );//Does NOT work
arr[i] = new MyClass;//This works
}
}
EDIT 2:
I forgot to mention, I also tried using the GetData method but it didn't work either:
MyClass **pData;
if ( arr.SetCount(initialCount) ) {
pData = arr.GetData();
for ( int i = 0; i < initialCount; i++, pData++ ) {
*pData = new MyClass;
}
}
All the three attempts to add elements DO work, but they don't do exactly the same thing, and - more important - the dangerous option does not crash the application and only creates a condition that causes crash later.
//arr.Add( new MyClass );//Does NOT work
//arr.SetAt( i, new MyClass );//Does NOT work
arr[i] = new MyClass;//This works
Let's see what the they actually do:
SetCount adds 10 NULL elements to the array
following Add leaves those ten nulls and adds your instances as 11th, 12th and on
following SetAt replaces NULLs with your instances
following indexed set replaces NULLs with your instances in the same way as #2 above
So items #2 and #3 do "work" and item #1 does a different thing: the array has 20 items and if you later attempt to access the elements, you hit NULLs where you expect to have valid pointers.
Have a look at small application that prints element count (you can see you have 10 or 20 elements), and then does element checking to verify if all elements of the array are "valid".
#include "stdafx.h"
#include <atlcoll.h>
class MyClass
{
private:
INT m_nValue;
public:
MyClass() :
m_nValue(0xDEADC0DE)
{
}
VOID Check()
{
ATLASSERT(m_nValue == 0xDEADC0DE);
}
};
int _tmain(int argc, _TCHAR* argv[])
{
CAtlArray<MyClass*> arr;
size_t initialCount = 10;
if(arr.SetCount(initialCount))
{
for( int i = 0; i < initialCount; i++ )
{
arr.Add( new MyClass );//Does NOT work
//arr.SetAt( i, new MyClass );//Does NOT work
//arr[i] = new MyClass; //This works
}
}
_tprintf(_T("arr.GetCount() %d\n"), arr.GetCount());
for(SIZE_T nIndex = 0; nIndex < arr.GetCount(); nIndex++)
arr[nIndex]->Check();
return 0;
}
An easier way to put elements to the array is as follows:
size_t initialCount = 10;
//if(arr.SetCount(initialCount)) -- not needed
{
for( int i = 0; i < initialCount; i++ )
{
arr.Add( new MyClass );
}
}

C++ resize array to smaller size keep same name delete old place in array

I have an array of space object (my thing) that I need to reduce but keep the same name in order to handle some collisions. I set my array up like:
ufo** ufoAr = new ufo*[numberOfUfos];
for (int i=0; i<numberOfUfos; i++) {
ufoAr[i] = new ufo(randomIntBetween(1630, 70), randomIntBetween(860, 45));
}
and when i detect a collision I want to resize my array with two less and delete the two specific elems of array. like here:
//look through all the ufoAr[]
for (int i=0; i<numberOfUfos; i++) {
//look through ufoAr[] again to see other objects
for(int j=0; j<10; j++) {
//if the same
if (i==j){ continue; }
else {
//find a collision
if(ufoAr[i]->collision(ufoAr[j]->sp)) {
//Array::Resize(ufoAr, numberOfUfos-2);
//numberOfUfos = numberOfUfos - 2;
// ------ TRY TO RESIZE ARRAY TO -2 BUT SAME NAME WITHOUT iTH AND jTH ELEM
ufoAlive[i] = false;
ufoAlive[j] = false;
}
}
}
}
I would greatly appreciate any help on resizing the array, thanks in advanced. I am really struggling and need another opinion. thanks
Jack
To do this, you will need to FIRST create a new array, e.g.
ufo** ufoArTmp = new ufo*[numberOfUfos-2];
then copy the contents [you want to keep] of ufoAr into ufoArTmp. Once that is done, you do delete [] ufoAr, and finally ufoAr = ufoArTmp; to update the original pointer. do NOT delete ufoArTmp at this point, as it's the same value as is now in ufoAr, and you want to keep that, right.
Obviously pay special attention to numberOfUfos being less than 2 when you start... ;)
Edit, in reading through the other code:
Don't do this:
if (i==j){ continue; }
else {
much better:
if (i!=j) {
The simplest way to do this is to use std::vector and let that handle the resizing for you.
cplusplus.com reference
cppreference page

Trying to fill a 2d array of structures in C++

As above, I'm trying to create and then fill an array of structures with some starting data to then write to/read from.
I'm still writing the cache simulator as per my previous question:
Any way to get rid of the null character at the end of an istream get?
Here's how I'm making the array:
struct cacheline
{
string data;
string tag;
bool valid;
bool dirty;
};
cacheline **AllocateDynamicArray( int nRows, int nCols)
{
cacheline **dynamicArray;
dynamicArray = new cacheline*[nRows];
for( int i = 0 ; i < nRows ; i++ )
dynamicArray[i] = new cacheline [nCols];
return dynamicArray;
}
I'm calling this from main:
cacheline **cache = AllocateDynamicArray(nooflines,noofways);
It seems to create the array ok, but when I try to fill it I get memory errors, here's how I'm trying to do it:
int fillcache(cacheline **cache, int cachesize, int cachelinelength, int ways)
{
for (int j = 0; j < ways; j++)
{
for (int i = 0; i < cachesize/(cachelinelength*4); i++)
{
cache[i][ways].data = "EMPTY";
cache[i][ways].tag = "";
cache[i][ways].valid = 0;
cache[i][ways].dirty = 0;
}
}
return(1);
}
Calling it with:
fillcache(cache, cachesize, cachelinelength, noofways);
Now, this is the first time I've really tried to use dynamic arrays, so it's entirely possible I'm doing that completely wrong, let alone when trying to make it 2d, any ideas would be greatly appreciated :)
Also, is there an easier way to do write to/read from the array? At the moment (I think) I'm having to pass lots of variables to and from functions, including the array (or a pointer to the array?) each time which doesn't seem efficient?
Something else I'm unsure of, when I pass the array (pointer?) and edit the array, when I go back out of the function, will the array still be edited?
Thanks
Edit:
Just noticed a monumentally stupid error, it should ofcourse be:
cache[i][j].data = "EMPTY";
You should find your happiness. You just need the time to check it out (:
The way to happiness

c++ Dynamic 2d array not using default constructor

I got a problem that is beyond my knowledge. I'm working on a HGE project, but this is a c++ issue, not the HGE engine itself.
The question:
I want to create a 2D array with 3 different animations on 5 different turtles. However, I need to use a constructor in HGE something like this;
turtleAnim[i] = new hgeAnimation( turtleTexture, 6, 6, 0, 0, 110, 78 )
But I don't know how to do it! All examples on the interwebz handle the problem as if it got a default constructor. Something like this:
in class:
#define TURTLECOUNT 5
#define TURTLEANIMATIONS 3
private:
hgeAnimation** turtleAnim;
in the.cpp
turtleAnim= new hgeAnimation*[TURTLECOUNT];
for(int i=0; i<TURTLECOUNT; i++)
{
turtleAnim[i]= new hgeAnimation[TURTLEANIMATIONS]; // Uses default constructor. I don't want that cuz it doesn't exists.
turtleAnim[i]->Play();
}
First, you have to decide whether you want your objects on the stack or the heap. Since they're objects, you probably want them on the heap, which means your 2D array will have 3 stars, and you will access the animations like this:
hgAnimation* theSecondAnimOnTheFourthTurtle = turtleAnim[4][2];
theSecondAnimOnTheFourthTurtle->DoSomething();
If that's what you want, then first you make the matrix of pointers.
hgeAnimation*** turtleAnim = new hgeAnimation**[TURTLECOUNT];
Then you can loop through the turtles. For each turtle, you make an array of pointers to the animations. For each element of that array, you make the animation itself.
for (int turt=0; turt<TURTLECOUNT; ++turt) {
turtleAnim[turt] = new hgeAnimation*[TURTLEANIMATIONS];
for (int ani=0; ani<TURTLEANIMATIONS; ++ani) {
turtleAnim[turt][ani] = new hgeAnimation(parameter1, par2, par3);
}
}
If that looks tricky, deleting all the arrays will be a pain too:
for (int turt=0; turt<TURTLECOUNT; ++turt) {
for (int ani=0; ani<TURTLEANIMATIONS; ++ani) {
delete turtleAnim[turt][ani];
}
delete[] turtleAnim[turt];
}
delete[] turtleAnim;
The fact that this is tricky is a good sign that there's probably a more simple way to design it.
How about a turtle class that has a member like:
class ATurtle {
private:
std::vector<hgeAnimation*> myAnimations;
Then in your class's constructor, you can do whatever you want in order to make the animations.
ATurtle::ATurtle(par1, par2, par3) {
myAnimations.push_back( new hgeAnimation(par1, x, y) );
myAnimations.push_back( new hgeAnimation(par2, z, a) );
myAnimations.push_back( new hgeAnimation(par3, b, c) );
}
That way, you can make your turtles in a single array:
ATurtle* turtles[TURTLECOUNT];
for (int t=0; t<TURTLECOUNT; ++t) {
turtles[t] = new ATurtle(par1, par2);
}
And in your turtle class, you would access the animations like so:
(*(myAnimations.at(1)))->DoSomething();
or
std::vector<hgAnimation*>::iterator i, end=myAnimations.end();
for (i=myAnimations.begin(); i!=end; ++i) {
(*i)->DoSomething();
}
You will still have to call delete on each element of your vector in this case, though, since you called new for every element.
ATurtle::~ATurtle() {
std::vector<hgAnimation*>::iterator i, end=myAnimations.end();
for (i=myAnimations.begin(); i!=end; ++i) {
delete (*i);
}
}

Deleting double pointer causes heap corruption

I am using a double pointer but when I try to delete it it causes Heap Corruption: CRT detected that the application wrote to memory after end of heap. It "crashes" inside the destructor of the object:
Map::~Map()
{
for(int i = 0; i < mTilesLength; i++)
delete mTiles[i];
delete[] mTiles;
}
mTiles is declared something like this:
Tile **mTiles = NULL;
mTiles = new Tile *[mTilesLength];
for(int i = 0; i < mTilesLength; i++)
mTiles[i] = new Tile(...);
If notable mTiles is a object of "Tile" which inherits from a object "Sprite" all 3 destructors are set as virtual (map, tile, sprite), not sure if that makes any difference but seemed to work until now.
The code you posted does not seem to have any problems in it. I created a simple, self contained, compiling (and correct) example from it:
struct Tile {int x; Tile():x(7) {}};
struct Map {
Tile **mTiles;
int mTilesLength;
Map(int TilesLength_);
~Map();
};
Map::~Map()
{
for(int i = 0; i < mTilesLength; i++) {
delete mTiles[i];
}
delete[] mTiles;
}
Map::Map(int TilesLength_):
mTiles(),
mTilesLength(TilesLength_)
{
mTiles = new Tile *[mTilesLength];
for(int i = 0; i < mTilesLength; i++) {
mTiles[i] = new Tile();
}
}
int main() {
Map* m = new Map(1000);
delete m;
}
I compiled and ran it <- link, and nothing bad was noticed.
Your problem lies in code you have not shared with us. In order to find the code that is causing the problem and ask the right question, go here: http://sscce.org/
Then take your code and start trimming parts off it until the code is simple, yet still demonstrates your heap corruption. Keep copies of each version as you trim away irrelevant code so you don't skip over the part where the problem occurs (this is one of the many reasons you want a version control system even on your personal projects).