Archived

This topic is now archived and is closed to further replies.

40 Thieves

delete [ ] array

Recommended Posts

40 Thieves    122
quick question for you guys: i have something like this: enum TEAM { EMPTY, RED, BLACK, FREE }; TEAM gameBoard[8][8]; in the global scope of my program. When I exit my program (the exit occurs within another function if that matters), do I need to delete my array or no? I tried to delete it with: delete [] &gameBoard; and I got no compile errors or build errors, but when i exited my program I get a debug error (in VC++ 6.0) which points to this line of code in dbgdel.cpp (not my file): /* verify block type */ _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)); Any help is appreciated (hopefully my stupidity can help others) Thanks in advance for any help. 40 www.databyss.com www.omlettesoft.com "Don''t meddle in the affairs of wizards, for they are subtle and quick to anger."

Share this post


Link to post
Share on other sites
Nate    122
No you don''t need to delete your array. You never called ''new'' so you don''t need to call delete. The memory for that array is allocated when the program starts and then is released when the program ends, this is all done behind the scenes.

Nate Miller
http://nate.scuzzy.net

Share this post


Link to post
Share on other sites
Mezz    571
TEAM *gamebaord = new TEAM[size];

I''m not sure how you (or if you can) allocate multi-dimensional arrays.

-Mezz

Share this post


Link to post
Share on other sites
jumble    122

    
enum TEAM { EMPTY, RED, BLACK, FREE };

TEAM(*gameboard)[8]; //this DOESNT allocate an array of pointers


gameboard = new TEAM[8][8];

delete [] gameboard;


I believe this is correct. You have to be wary when dealing with multidimensional arrays with the new keyword. Also in your example you specified the &address of gameboard, that isn''t needed when you are handling arrays.

Hope this helps...

jumble
-----------
Microsoft patents ones and zeroes - remind you of Hasbro?

Share this post


Link to post
Share on other sites
null_pointer    289
jumble:

Unfortunately, your solution won''t work. A multidimensional array is really just an array of pointers, where each pointer points to a single-dimensional array.

Perhaps I''d better explain with source code - I didn''t get it for many months until I saw a post on gamedev.


40 Thieves:

Here is source code that illustrates how to allocate, use, and deallocate a dynamic 2-dimensional array (i.e., TEAM[8][8]).


enum TEAM { EMPTY, RED, BLACK, FREE };

int main(int argc, char* argv[])
{
const int dimension1 = 8; // size of first dimension you want
const int dimension2 = 8; // size of second dimension you want

// begin to allocate the array
TEAM* gameboard[dimension1]; // array of arrays - that''s a multidimensional array

//////////////////////////////////////////////////////////////////////////////////////////////////////
// here is what the memory looks like so far:
//
// gameboard[0] -> (nothing yet)
// gameboard[1] -> (nothing yet)
// gameboard[2] -> (nothing yet)
// gameboard[3] -> (nothing yet)
// gameboard[4] -> (nothing yet)
// gameboard[5] -> (nothing yet)
// gameboard[6] -> (nothing yet)
// gameboard[7] -> (nothing yet)
//////////////////////////////////////////////////////////////////////////////////////////////////////

for( int x=0; x < dimension2; x++ )
gameboard[x] = new TEAM[dimension2]; // allocate each array

//////////////////////////////////////////////////////////////////////////////////////////////////////
// here is what the memory looks like now:
//
// gameboard[0] -> new TEAM[0], TEAM[1], TEAM[2], TEAM[3], TEAM[4], TEAM[5], TEAM[6], TEAM[7]
// gameboard[1] -> new TEAM[0], TEAM[1], TEAM[2], TEAM[3], TEAM[4], TEAM[5], TEAM[6], TEAM[7]
// gameboard[2] -> new TEAM[0], TEAM[1], TEAM[2], TEAM[3], TEAM[4], TEAM[5], TEAM[6], TEAM[7]
// gameboard[3] -> new TEAM[0], TEAM[1], TEAM[2], TEAM[3], TEAM[4], TEAM[5], TEAM[6], TEAM[7]
// gameboard[4] -> new TEAM[0], TEAM[1], TEAM[2], TEAM[3], TEAM[4], TEAM[5], TEAM[6], TEAM[7]
// gameboard[5] -> new TEAM[0], TEAM[1], TEAM[2], TEAM[3], TEAM[4], TEAM[5], TEAM[6], TEAM[7]
// gameboard[6] -> new TEAM[0], TEAM[1], TEAM[2], TEAM[3], TEAM[4], TEAM[5], TEAM[6], TEAM[7]
// gameboard[7] -> new TEAM[0], TEAM[1], TEAM[2], TEAM[3], TEAM[4], TEAM[5], TEAM[6], TEAM[7]
//
// in other words, we now have an 8x8 array!
//////////////////////////////////////////////////////////////////////////////////////////////////////

// test it!
gameboard[2][7] = RED;
gameboard[1][4] = BLACK;

// now we destroy the array
for( int y=0; y < dimension2; y++ )
delete[] gameboard[y];

//////////////////////////////////////////////////////////////////////////////////////////////////////
// here is what the memory looks like now:
//
// gameboard[0] -> (deleted)
// gameboard[1] -> (deleted)
// gameboard[2] -> (deleted)
// gameboard[3] -> (deleted)
// gameboard[4] -> (deleted)
// gameboard[5] -> (deleted)
// gameboard[6] -> (deleted)
// gameboard[7] -> (deleted)
//
// the array of pointers that we allocated earlier on the stack will simply go out of scope
//////////////////////////////////////////////////////////////////////////////////////////////////////

return 0;
}





- null_pointer
Sabre Multimedia

Share this post


Link to post
Share on other sites
jumble    122
Mr. Pointer - i''ve just looked up the new keyword in MSDN and it basically says exactly what i said. I put my code into MSVC 6 and it compiled fine... im not sure if it actually worked in practice though.

Hmmm... i''m going to go and make a simple proggy using it.... perhaps the MSVC compiler allows my code?

jumble
-----------
Microsoft patents ones and zeroes - remind you of Hasbro?

Share this post


Link to post
Share on other sites
Mr Cucumber    122
Your code will work jumble because you can create a twodimensional array if one of the array size (the first one I believe) is a constant value.
However if you wan''t to create a completely dynamic twodimensional array you have to go with null_pointer''s solution.

Share this post


Link to post
Share on other sites
The_[PI]_ehT    122
Well, null_pointer is right mostly, but at least it won't be *totally* dynamic. If you want it completely dynamic, do it like the following:


// the pointer to pointer(s) to type TEAM
TEAM ** gameboard;

//////////////////////////////////////////
// at the moment, memory looks like this:
//
// gameboard -> (nothing yet, points to NULL )
//
//////////////////////////////////////////

// first _dynamically_ create the array of pointers
gameboard = ( TEAM **)malloc( many_times * sizeof( TEAM * ) );

//////////////////////////////////////////////////////////////////////////////////////////////////////
// here is what the memory looks like now
//
// gameboard[0] -> (nothing yet)
// gameboard[..] -> (nothing yet)
// gameboard[n] -> (nothing yet)
//////////////////////////////////////////////////////////////////////////////////////////////////////

// Afterwards, you have to allocate each field of the array as null_pointer said:
for( int x=0; x < as_many_elements_as_you_want; x++ )
{
gameboard[x] = new TEAM;
};

//////////////////////////////////////////////////////////////////////////////////////////////////////
// here is what the memory looks like now:
//
// gameboard[0] -> new TEAM[0], TEAM[..], TEAM[n2]
// gameboard[..] -> new TEAM[0], TEAM[..], TEAM[n2]
// gameboard[n] -> new TEAM[0], TEAM[..], TEAM[n2]
//
// in other words, we do now have an n*n2 array
//////////////////////////////////////////////////////////////////////////////////////////////////////

// now you can access it easily using the standard array style
gameboard[0][1] = RED;
gameboard[1][0] = FREE; // and so on

// now it's up to destroy the whole thing
for( x=0; x < as_many_elements_as_you_want; x++ )
{
delete[] gameboard[x];
};

//////////////////////////////////////////////////////////////////////////////////////////////////////
// here is what the memory looks like now:
//
// gameboard[0] -> (deleted)
// gameboard[..] -> (deleted)
// gameboard[n] -> (deleted)
//
//////////////////////////////////////////////////////////////////////////////////////////////////////

// note that the array of pointers will not go out of scope automatically, we have to free the memory by ourselves
free( gameboard );

// now we're done.



So now you got a simple dynamical but twodimensional array
btw, it works as well with all other types.
This is similar to null_pointer's version, but it's better if you want, for example, open a map with an unknown size.
Keep in mind that you're able to use pointers to structs here as well, or classes... I think you got the point.

hope this helps,

pi~

p.s.:
sorry null_pointer had to borrow your source. it was a good explanation of the principles but it was not dynamic enough for me
(hell i like playing with pointers and... *access violation -> tried to think whithout allocating memory*)

silly board... ate all my formattings... never use i in loops for arrays... looks strange then...

Edited by - The_[PI]_ehT on July 23, 2000 1:23:46 PM

Share this post


Link to post
Share on other sites
Wilka    122
Pointers to pointers, mixing malloc with new and running the risk of leaks. Not my kind of thing at all (not anymore anyway). Here's a nicer way (at least I think it is), and you don't need to (explicitly) new or delete anything.

        
#include <vector>
using std::vector;

enum TEAM { EMPTY, RED, BLACK, FREE };

int main(int argc, char* argv[])
{
const int dimension1 = 8; // size of first dimension you want

const int dimension2 = 8; // size of second dimension you want


//define a vector that holds 'TEAMs

typedef vector<TEAM> TEAM_vector;

//to get a 2 dimensions vector of TEAMs we need to create a vector of team vectors

typedef vector<TEAM_vector> TEAM_vector2D;

//now create the actual 2d vector

//one of the vectors constructors takes a size, and a default value for the type
//so we pass 'dimension1' as the size. For the value of each item in the vector,
//we pass in a temp TEAM_vector of the size we want (dimension2). each item in
//the inner vector will have its default constructor called. So for TEAM it'll

//be set to EMPTY

TEAM_vector2D gameboard(dimension1, TEAM_vector(dimension2));

//////////////////////////////////////////////////////////////////////////////////////////////////////

// here is what the vector looks like after creation

//

// gameboard[0] -> vector<TEAM> - size is dimension2 (8)
// gameboard[1] -> vector<TEAM> - size is dimension2 (8)
// gameboard[2] -> vector<TEAM> - size is dimension2 (8)
// gameboard[3] -> vector<TEAM> - size is dimension2 (8)
// gameboard[4] -> vector<TEAM> - size is dimension2 (8)
// gameboard[5] -> vector<TEAM> - size is dimension2 (8)
// gameboard[6] -> vector<TEAM> - size is dimension2 (8)
// gameboard[7] -> vector<TEAM> - size is dimension2 (8)
//

// in other words, we now have an 8x8 array! <img src="smile.gif" width=15 height=15 align=middle>
//////////////////////////////////////////////////////////////////////////////////////////////////////


// test it!

gameboard[2][7] = RED;
gameboard[1][4] = BLACK;

//the vector will take care of it's own memory so we don't need delete anything.

return 0;
}


Using a vector isn't any slower than using a raw array (apart from the extra temp created for the constructor), and it saves you from needing to delete anything (I don't like 'tidy up' code). Also you can easily change the size of the array at runtime using vector.resize or vector.push_back & vector.pop_back.

PS you don't need to use a typedef, I only used them so I could split up the vector definition a little.

Edited by - Wilka on July 23, 2000 2:56:59 PM

Share this post


Link to post
Share on other sites
null_pointer    289
jumble:

Must be my mistake...

VC displays every element of your pointer array as having the same memory address, but that is probably just a bug in the variables window. Actually, your solution does work fine, and it''s also quite a bit better than mine for arrays bigger than 2 dimensions, but it only works when the size of all dimensions but the first is constant.


Mr. Cucumber:

Actually, only the first dimension in an array can be variable. All other dimensions must be constant. Don''t ask me why...


The_[PI]_ehT:

Yes, my solution is not totally allocated on the heap (actually, nothing seems to be...you always need a stack-based pointer to it, or a stack based pointer to a heap-based pointer to it, or...etc.). However, the array dimensions do not have to be constant in my example - that was merely to give the 8''s a name so the reader could tell the first dimension from the second dimension. You could just as easily have used variables for the dimensions.

BTW, you can also use new to allocate an array of pointers:


gameboard = new TEAM*[many_times];



And delete them:


delete[] gameboard;



There doesn''t seem to be any reason to use malloc in C++ outside of the new operator.


Wilka:

Always the STL person, huh?

...just kidding! I like vectors better, too, but I think that one has to learn how arrays work before learning vector.




- null_pointer
Sabre Multimedia

Share this post


Link to post
Share on other sites
Wilka    122
quote:

Wilka:

Always the STL person, huh?



Yep

I''ve my fair share of bugs cased by dynamic arrays, and since I started using STL I''ve found a reason to use new[] over vector. So I''m probably trying to get as many people as I can to start using STL as well

quote:

...just kidding! I like vectors better, too, but I think that one has to learn how arrays work before learning vector.



I agree with you here, but I''m not sure if we''re right .

Would it really make much of difference if you''ve done it manually first before you start using vector? It''ll give you a better understand of what vector actually does, but you really need to know to be able to use vector properly?

If things like std::vector and std::string where using instead of new[] and char* when teaching people C++, it would probably make it a lot easier for them to learn - they wouldn''t need to worry about memory management etc. (which is probably one of the hardest things for people new to C++). Obviously they should be taught about new[] and char* (maybe have them make their own vector class), just not during the first lesson

Share this post


Link to post
Share on other sites
Wilka    122
quote:

VC displays every element of your pointer array as having the same memory address, but that is probably just a bug in the variables window.



It''s not a bug, it''s a feature

In a debug build, MSVC sets all pointers to "0xcccccccc" by default. It''s to help with debugging, if you see a pointer with that value you know it hasn''t been properly initialised.

I''ve also seen the value "0xcdcdcdcd" in a few places, but I''m not sure what it means (maybe after a delete?).

I''ve just had a quick check, and it looks like "0xcdcdcdcd" is the default for variables allocated on the heap, and "0xcccccccc" is for variables on the stack of any type (not just pointers).

Share this post


Link to post
Share on other sites