127 - "Accordian" Patience
Moderator: Board moderators
-
- Guru
- Posts: 584
- Joined: Thu Jun 19, 2003 3:48 am
- Location: Sanok, Poland
- Contact:
-
- Experienced poster
- Posts: 114
- Joined: Wed Jul 30, 2003 10:30 pm
- Location: Newfoundland, Canada (St. John's)
Hmm.. I compiled it with cygwin under Win98 and it also works. 
What memory is not allocated? I mean, DO allocate the memory for piles, and in my Pile constructor I allocate memory for the data structures needed there.
I'm on my girlfriend's computer now and its really hard to fix a problem that doesn't happen (at least on this computer).

What memory is not allocated? I mean, DO allocate the memory for piles, and in my Pile constructor I allocate memory for the data structures needed there.
I'm on my girlfriend's computer now and its really hard to fix a problem that doesn't happen (at least on this computer).
-
- Guru
- Posts: 584
- Joined: Thu Jun 19, 2003 3:48 am
- Location: Sanok, Poland
- Contact:
-
- Guru
- Posts: 584
- Joined: Thu Jun 19, 2003 3:48 am
- Location: Sanok, Poland
- Contact:
[cpp]int main ()
{
char *card = new char[2];
while (cin >> card)
{
...
piles[npiles++].push(card);
....
delete [] piles;
....
}
}[/cpp]
Okay, so initially you have a pointer to a two character array stored in *card, correct? .. Okay, so then you push it into your pile .. so now the pile also has a pointer to this same two character array, correct? .. And then at the end you need to free up memory, so you call the Pile's destructor, which deletes all the cards that it contains, right? .. So what happened to the original *char pointer? (esp. think about when you try to cin >> card a second time)
If you want more substantiveproof, try adding:
[c]printf ("%p\n", card);[/c]
after you allocate the card, and when you're deleting the cards in the pile .. You should see that one of the cards in the pile will equal what was in *card .. (not sure how to output a pointer using cout...)
P.S. Also, remember that "new char*[52]" allocates an array of pointers.
{
char *card = new char[2];
while (cin >> card)
{
...
piles[npiles++].push(card);
....
delete [] piles;
....
}
}[/cpp]
Okay, so initially you have a pointer to a two character array stored in *card, correct? .. Okay, so then you push it into your pile .. so now the pile also has a pointer to this same two character array, correct? .. And then at the end you need to free up memory, so you call the Pile's destructor, which deletes all the cards that it contains, right? .. So what happened to the original *char pointer? (esp. think about when you try to cin >> card a second time)
If you want more substantiveproof, try adding:
[c]printf ("%p\n", card);[/c]
after you allocate the card, and when you're deleting the cards in the pile .. You should see that one of the cards in the pile will equal what was in *card .. (not sure how to output a pointer using cout...)
P.S. Also, remember that "new char*[52]" allocates an array of pointers.
-
- Guru
- Posts: 584
- Joined: Thu Jun 19, 2003 3:48 am
- Location: Sanok, Poland
- Contact:
-
- Guru
- Posts: 584
- Joined: Thu Jun 19, 2003 3:48 am
- Location: Sanok, Poland
- Contact:
-
- Experienced poster
- Posts: 114
- Joined: Wed Jul 30, 2003 10:30 pm
- Location: Newfoundland, Canada (St. John's)
I still am confused as to what's happening here. With the assumption that I put a delete [] piles at the end of the while loop:
At the beginning of the while loop, 52 new piles get allocated. So, if I deallocate these at the end of the while loop, won't they get reallocated next time around?
I put a cout in the destructor of Pile, and saw it was getting called 52 times. The crash doesn't happen within the destructor. Actually, it happend the second time around in the for(i=1 to 52) loop.
This makes me wonder, if it works the first time through the while loop, why won't it work the second time around?
Here's a modified version of my program. It is cleaned up a little. If anyone knows C++ well, can he help me figure out what is wrong with my memory routines?
Also, am I right the using delete only deletes the memory allocated to a pointer, and not a pointer itself?
[cpp]#include <iostream>
class Pile {
private:
int ncards;
char **cards;
public:
Pile() {
ncards = 0;
cards = new char * [52];
}
~Pile() {
for(char **p = cards; p < cards+ncards; p++)
delete [] *p;
delete [] cards;
}
void push(char *card) {
cards[ncards] = new char [2];
cards[ncards][0] = card[0];
cards[ncards][1] = card[1];
ncards++;
}
void pop() {
if(ncards > 0) {
char *p = cards[ncards-1];
delete [] p;
ncards--;
}
}
char* top() {
char *p = new char [2];
p[0] = cards[ncards-1][0];
p[1] = cards[ncards-1][1];
return p;
}
bool isEmpty()
{return (ncards == 0);}
int size()
{return ncards;}
};
int npiles;
Pile *piles;
inline void remove(int pos) {
for(int i = pos; i < npiles-1; i++)
piles = piles[i+1];
npiles--;
}
bool makeMove() {
for(int i = 1; i < npiles; i++) {
char *cardA = piles.top();
int diff = (i > 2) ? 3 : 1;
while(diff > 0) {
char *cardB = piles[i-diff].top();
if(cardA[0] == cardB[0] || cardA[1] == cardB[1]) {
piles[i-diff].push(cardA);
piles.pop();
if(piles.isEmpty()) remove(i);
return true;
}
diff -= 2;
}
}
return false;
}
using namespace std;
int main() {
char card[2];
while(cin >> card) {
if(card[0] == '#') return 0;
npiles = 0;
piles = new Pile[52];
piles[npiles++].push(card);
for(int i = 1; i < 52; i++) {
cin >> card;
piles[npiles++].push(card);
}
while(makeMove());
cout << npiles << " pile" << (npiles > 1 ? "s" : "") << " remaining:";
for(Pile *p = piles; p < piles+npiles; p++) cout << " " << p->size();
cout << endl;
delete [] piles;
}
return 0;
}[/cpp]
At the beginning of the while loop, 52 new piles get allocated. So, if I deallocate these at the end of the while loop, won't they get reallocated next time around?
I put a cout in the destructor of Pile, and saw it was getting called 52 times. The crash doesn't happen within the destructor. Actually, it happend the second time around in the for(i=1 to 52) loop.
This makes me wonder, if it works the first time through the while loop, why won't it work the second time around?
Here's a modified version of my program. It is cleaned up a little. If anyone knows C++ well, can he help me figure out what is wrong with my memory routines?
Also, am I right the using delete only deletes the memory allocated to a pointer, and not a pointer itself?
[cpp]#include <iostream>
class Pile {
private:
int ncards;
char **cards;
public:
Pile() {
ncards = 0;
cards = new char * [52];
}
~Pile() {
for(char **p = cards; p < cards+ncards; p++)
delete [] *p;
delete [] cards;
}
void push(char *card) {
cards[ncards] = new char [2];
cards[ncards][0] = card[0];
cards[ncards][1] = card[1];
ncards++;
}
void pop() {
if(ncards > 0) {
char *p = cards[ncards-1];
delete [] p;
ncards--;
}
}
char* top() {
char *p = new char [2];
p[0] = cards[ncards-1][0];
p[1] = cards[ncards-1][1];
return p;
}
bool isEmpty()
{return (ncards == 0);}
int size()
{return ncards;}
};
int npiles;
Pile *piles;
inline void remove(int pos) {
for(int i = pos; i < npiles-1; i++)
piles = piles[i+1];
npiles--;
}
bool makeMove() {
for(int i = 1; i < npiles; i++) {
char *cardA = piles.top();
int diff = (i > 2) ? 3 : 1;
while(diff > 0) {
char *cardB = piles[i-diff].top();
if(cardA[0] == cardB[0] || cardA[1] == cardB[1]) {
piles[i-diff].push(cardA);
piles.pop();
if(piles.isEmpty()) remove(i);
return true;
}
diff -= 2;
}
}
return false;
}
using namespace std;
int main() {
char card[2];
while(cin >> card) {
if(card[0] == '#') return 0;
npiles = 0;
piles = new Pile[52];
piles[npiles++].push(card);
for(int i = 1; i < 52; i++) {
cin >> card;
piles[npiles++].push(card);
}
while(makeMove());
cout << npiles << " pile" << (npiles > 1 ? "s" : "") << " remaining:";
for(Pile *p = piles; p < piles+npiles; p++) cout << " " << p->size();
cout << endl;
delete [] piles;
}
return 0;
}[/cpp]
You're not deallocating correctly .. Well, actually, more correctly, you're trying to delete a lot of the same pointers .. Here's some code that might help you debug further this phenomena (basically, label each unique object with it's own identification code):
[cpp]static int PileID = 0;
class Pile
{
private:
int id;
...
public:
Pile ()
{
id = PileID++;
cout << "Pile(" << id << ") - constructing..." << endl;
...
}
~Pile ()
{
cout << "Pile(" << id << ") - destructing..." << endl;
...
}
}[/cpp]
You should get 52 distinct constructing and 52 distinct destructing messages, but you only get 7 distinct destructing messages (the unique 6 piles that are left, and the the empty piles) for the first set of cards. Since I'm no expert on internal C++ memory management, I can't say why doing two deletes on the same pointer doesn't 'cause an immediate crash, but that is where the problem actually lies, not necessarily in the "cin >> card" statement in the for(1..51) loop in main(). [Perhaps it only queues the deletes up somewhere and only goes deleting the memory after some other non-deletes are executed, *shrug*]
The delete function will remove the memory pointed to by a pointer. The pointer itself will remain unchanged and will continue to point to the now unallocated memory (which will 'cause unknown errors if you try to access the memory again) until you either update it to some new location, or it goes out of scope and disappears forever.
[cpp]static int PileID = 0;
class Pile
{
private:
int id;
...
public:
Pile ()
{
id = PileID++;
cout << "Pile(" << id << ") - constructing..." << endl;
...
}
~Pile ()
{
cout << "Pile(" << id << ") - destructing..." << endl;
...
}
}[/cpp]
You should get 52 distinct constructing and 52 distinct destructing messages, but you only get 7 distinct destructing messages (the unique 6 piles that are left, and the the empty piles) for the first set of cards. Since I'm no expert on internal C++ memory management, I can't say why doing two deletes on the same pointer doesn't 'cause an immediate crash, but that is where the problem actually lies, not necessarily in the "cin >> card" statement in the for(1..51) loop in main(). [Perhaps it only queues the deletes up somewhere and only goes deleting the memory after some other non-deletes are executed, *shrug*]
The delete function will remove the memory pointed to by a pointer. The pointer itself will remain unchanged and will continue to point to the now unallocated memory (which will 'cause unknown errors if you try to access the memory again) until you either update it to some new location, or it goes out of scope and disappears forever.
-
- Experienced poster
- Posts: 114
- Joined: Wed Jul 30, 2003 10:30 pm
- Location: Newfoundland, Canada (St. John's)
This is where I am confused.. I thought I WAS updating it at the beginning of the while loop. Specifically, piles = new Pile[52]. Wouldn't that reallocate another 52 Piles? Obviously its not, because when I try to push something on the second pile, I get the crash. However, through debugging I noticed that it successfully pushes a card on the FIRST pile. Its only when it tries to push a card on the second pile that I get a crash.UFP2161 wrote: The delete function will remove the memory pointed to by a pointer. The pointer itself will remain unchanged and will continue to point to the now unallocated memory (which will 'cause unknown errors if you try to access the memory again) until you either update it to some new location, or it goes out of scope and disappears forever.
EDIT::
I also tried what you said with the id#, and found that the destructors are messed up. The same pile gets destructed many times. My question is: does anyone know how I can delete my array of piles, and reallocate them again later? Seems simple enough, huh?
