C++ error/help, new question

Glitchny

Diamond Member
Sep 4, 2002
5,679
1
0
Hey guys i need some help and i dont really know where else to ask. The little program i made creates a stack object, and the size of the stack is dynamic so that a user can make it as large or as small as they like. I had it working perfectly in my schools computer lab on win2k and now for some reason when i try to run it on my comp at my room i get an error. Not a compile time error, i just get a critical error popup and the program crashes.... any ideas why? is there a reason that xp would make the pr0ogram function differently?

the new question is in my last post
 

Glitchny

Diamond Member
Sep 4, 2002
5,679
1
0
yeah ill post it
and all it does is initiliaze the arracy to c's and then outputs them, thats all. just testing it

#include <iostream>
#include <iomanip>
using namespace std;

const int MAX_ITEMS = 20;

class StackType
{
public:

StackType( );
StackType(int size);
bool IsFull () const;
bool IsEmpty() const;
void Push(char item );
void Pop();
char Top();
bool IsAllocated();
void Delete();
private:
int top;
char *ptr;
int size;

};



#include "template.h"
StackType::StackType()
{
ptr = new char[MAX_ITEMS];
top = -1;

while(!IsFull())
Push(0);
}
StackType::StackType(int size)
{
ptr = new char[size];
top = -1;

for(int i=0; i<size; i++)
Push('c');
}
bool StackType::IsEmpty() const
{
return(top == -1);
}

bool StackType::IsFull() const
{
return (top == MAX_ITEMS-1);
}
void StackType:ush(char newItem)
{
/*if( IsFull() )
throw FullStack():*/
top++;
ptr[top] = newItem;
}

void StackType:op()
{
/*if( IsEmpty() )
throw EmptyStack();*/
top--;
}

char StackType::Top()
{
/*if (IsEmpty())
throw EmptyStack();*/
return ptr[top];
}
bool StackType::IsAllocated()
{
if (ptr = NULL)
return false;
else
return true;
}
void StackType:elete()
{
delete ptr;
}





#include "template.h"

void main()
{
int stacksize = 0;
cout<<"How big would you like to make the stack? \n";
cin>>stacksize;

StackType info(stacksize);

if(!info.IsAllocated())
cout<<"Memory could not be allocated \n";

for(int i =0; i<stacksize;i++)
{
cout<<i+1<<setw(5)<<info.Top()<<endl;
info.Pop();
}
info.Delete();
}


according to the debugger the problem lies in the member function Top but i dont know how or why
 

irl33thax0r

Member
Mar 8, 2003
34
0
0
Have you recompiled it on your home computer? That may do something... also, through my experience, runtime errors are 99% of the time a memory error. This means, check all your pointers to make sure you are accessing them in the way they were meant to be accessed. I'm guessing its something along the lines of that.

P.S. Also my last idea, try running the program in compatibility mode as if it were 2k. See if that makes a difference.
 

Glitchny

Diamond Member
Sep 4, 2002
5,679
1
0
yes i recompiled it on my home comp but ill try again, and i think its a memory error but i dont know where, and thanx for the advice ill check the pointers
 

glugglug

Diamond Member
Jun 9, 2002
5,340
1
81
The way your top index works everywhere else the top() function is returning one element below the top of the stack.

Which when the stack gets down to one element is before the first actual allocated space.
 

Glitchny

Diamond Member
Sep 4, 2002
5,679
1
0
how is the top function returning the item under top? it returns ptr[top] which should be the top of the stack... i dont understand what u are trying to say
 

Glitchny

Diamond Member
Sep 4, 2002
5,679
1
0
ok from tyesting it out myself and replacing the return ptr[top]; line with return 'a'; or any other single charcter the program works, so for some reason i cant have it return ptr[top] on my comp here and i dont know why still
 

TheDiggler

Senior member
Dec 23, 2002
695
0
0
Originally posted by: Glitchny
yeah ill post it
and all it does is initiliaze the arracy to c's and then outputs them, thats all. just testing it

#include <iostream>
#include <iomanip>
using namespace std;

const int MAX_ITEMS = 20;

class StackType
{
public:

StackType( );
StackType(int size); // Variable 'size' is a class member. You can't re-use it here
bool IsFull () const;
bool IsEmpty() const;
void Push(char item );
void Pop();
char Top();
bool IsAllocated();
void Delete();
private:
int top;
char *ptr;
int size; // See comments for constructor StackType(int)

};



#include "template.h"
StackType::StackType()
{
ptr = new char[MAX_ITEMS];
top = -1;

while(!IsFull())
Push(0);
}

// See comments above about passed in variable 'size'
StackType::StackType(int size)
{
ptr = new char[size];
top = -1;

for(int i=0; i<size; i++)
Push('c');
}

bool StackType::IsEmpty() const
{
return(top == -1);
}

bool StackType::IsFull() const
{
return (top == MAX_ITEMS-1);
}

void StackType:ush(char newItem)
{
/*if( IsFull() )
throw FullStack():*/
top++;
ptr[top] = newItem;
}

void StackType:op()
{
/*if( IsEmpty() )
throw EmptyStack();*/
top--;
}

char StackType::Top()
{
/*if (IsEmpty())
throw EmptyStack();*/
return ptr[top];
}
bool StackType::IsAllocated()
{
if (ptr = NULL)
return false;
else
return true;
}
void StackType:elete()
{
delete [] ptr; // You new'd an ARRAY. use "delete []" to delete an array.
}

#include "template.h"

void main()
{
int stacksize = 0;
cout<<"How big would you like to make the stack? \n";
cin>>stacksize;

StackType info(stacksize);

if(!info.IsAllocated())
cout<<"Memory could not be allocated \n";

for(int i =0; i<stacksize;i++)
{
cout<<i+1<<setw(5)<<info.Top()<<endl;
info.Pop();
}
info.Delete();
}
*EDIT* First, look at my comments in the quote above

Try implementing the following recommended changes:


class StackType
{
public:

StackType( );
StackType(int stackSize);
bool IsFull () const;
bool IsEmpty() const;
void Push(char item );
void Pop();
char Top();
bool IsAllocated();
void Delete();
private:
int top;
char *ptr;
int size; // No longer conflicts with constructor StackType(int)

};

StackType::StackType()
{
StackType(MAX_ITEMS); // Invokes StackType(int stackSize) constructor instead of duplicating similar code in here.
}


StackType::StackType(int stackSize)
{
ptr = new char[stackSize];
top = -1;
size = stackSize;

for(int i=0; i<size; i++)
Push('c');
}

bool StackType::IsFull() const
{
return (top == size-1);
}

void StackType:ush(char newItem)
{
if( IsFull() ) throw FullStack(); //Uncommented this call
top++;
ptr[top] = newItem;
}

void StackType:op()
{
if ( IsEmpty() ) throw EmptyStack(); // Uncommented this call
top--;
}

bool StackType::IsAllocated()
{
return (ptr != NULL); // Simplified logic
}


Final Note: It's more appropriate for the Pop() method to return the top-most element (or NULL if the stack is empty) instead of void. If you do that, you can eliminatte the Top() method AND simplify main by doing something like this:

while ( ! ( info.IsEmpty() ) )
cout<<i+1<<setw(5)<<info.Pop()<<endl;

*EDIT* If you change Pop() to return a value, the Exception Handler will kick in if the stack's empty. Thus, you need only return the TOP MOST VALUE if it get that far in the method.
 

Glitchny

Diamond Member
Sep 4, 2002
5,679
1
0
thanx so much, i made the changes and it works now, i dont know why it didnt work on this comp but on the one in class and this is neater after the changes. i will uncomment the error handling code but i had commented it out to make things a little easier since this is my first attempt using pointers.

thanx again
 

glugglug

Diamond Member
Jun 9, 2002
5,340
1
81
OK, looking at it again the top variable is the last element put on the stack (I thought the increment was after the value setting before and the decrement was before it in the pop... but looking at it again this isn't the case). But then I don't know why it would have been blowing up.

Note: the delete function should have delete ptr[] since its an array being deleted but this is unlikely to be the cause I think.

I suspect the cause is something I didn't notice before: in your old isAllocated function you have a single = instead of a == This changes ptr to NULL.
 

TheDiggler

Senior member
Dec 23, 2002
695
0
0
Originally posted by: glugglug
I suspect the cause is something I didn't notice before: in your old isAllocated function you have a single = instead of a == This changes ptr to NULL.
Yeah, that's probably the true culprit of the original code!

*EDIT* Good catch BTW. My in-depth review of the code failed to catch that bug (even though I took care of it w/ my simplified logic)! :Q
 

Glitchny

Diamond Member
Sep 4, 2002
5,679
1
0
ah ok the = was probally the reason but it is better to have it simplified so it worked out, thanx alot guys it was really helpful
 

arcain

Senior member
Oct 9, 1999
932
0
0
StackType::StackType()
{
StackType(MAX_ITEMS); // Invokes StackType(int stackSize) constructor instead of duplicating similar code in here.
}

That will NOT do what you expect. You cannot call one constructor from another. What actually happens here is it will construct a temporary StackType object (within the constructor) but it will not construct "this" StackType object.

You also CANNOT call it like: "this->StackType(MAX_ITEMS);"
 

Glitchny

Diamond Member
Sep 4, 2002
5,679
1
0
it works in the code though, i implemented it and havent had problems with it.
What exactly wont work? since i have never called a constructor form a constructor either
 

TheDiggler

Senior member
Dec 23, 2002
695
0
0
Originally posted by: arcain
StackType::StackType()
{
StackType(MAX_ITEMS); // Invokes StackType(int stackSize) constructor instead of duplicating similar code in here.
}

That will NOT do what you expect. You cannot call one constructor from another. What actually happens here is it will construct a temporary StackType object (within the constructor) but it will not construct "this" StackType object.

You also CANNOT call it like: "this->StackType(MAX_ITEMS);"

Not true on all accounts; however, it would have been more accurate to code it as:

StackType::StackType()
{
return StackType(MAX_ITEMS); // Invokes StackType(int stackSize) constructor instead of duplicating similar code in here.
}

- You most certainly can call other constructors within constructors. I don't know where you got the notion that you can't. It executes the other constructor call on the CURRENT OBJECT (i.e. "this->"), not a TEMPORARY OBJECT.
- Once you're in the BODY of a constructor "this->" exists. Thus you can even invoke:
this->StackType(MAX_ITEMS);
 

Glitchny

Diamond Member
Sep 4, 2002
5,679
1
0
ok thanx it was working fine so i didnt know what the problem was but now that that is cleared up i think im error free

putting the return line in there causes the program to have errors so i just left it out
 

glugglug

Diamond Member
Jun 9, 2002
5,340
1
81
You can just make MAX_ITEMS a default value for the size param and then don't need a default constructor.
 

arcain

Senior member
Oct 9, 1999
932
0
0
Originally posted by: Glitchny
it works in the code though, i implemented it and havent had problems with it.
What exactly wont work? since i have never called a constructor form a constructor either

Consider the example (stolen from an example from the standard, it's actually a copy of the draft, but whatever) :

class X {
// ...
public:
// ...
X(int);
X(const X&);
~X();
};

X f(X);
void g()
{
X a(1);
X b = f(X(2));
a = f(a);
}

The line we're considered about is:
X b = f(X(2));

f takes a variable of type X as its parameter, so we construct a temporary X (constructed with a value of 2).

We can drop the assignment and end up with:
f(X(2));
Which is still valid C++..

in fact we can drop the function call too, so that we just have:
X(2)
and still have valid C++, and we know this constructs a temporary X, right?

If we move that into X's constructor.. what does it do? The meaning of that statement doesn't change, and it still creates a temporary X.


How do I know this? Because it bit me in the ass a couple months ago. It may work for you with your compiler (some compilers "help" you by initializing uninitialized variables to 0 when building in debug mode), but did not work for me under GCC.
 

TheDiggler

Senior member
Dec 23, 2002
695
0
0
Originally posted by: arcain
class X {
// ...
public:
// ...
X(int);
X(const X&);
~X();
};

X f(X);
void g()
{
X a(1);
X b = f(X(2));
a = f(a);
}

The line we're considered about is:
X b = f(X(2));

f takes a variable of type X as its parameter, so we construct a temporary X (constructed with a value of 2).

We can drop the assignment and end up with:
f(X(2));
Which is still valid C++..

in fact we can drop the function call too, so that we just have:
X(2)
and still have valid C++, and we know this constructs a temporary X, right?

If we move that into X's constructor.. what does it do? The meaning of that statement doesn't change, and it still creates a temporary X.

How do I know this? Because it bit me in the ass a couple months ago. It may work for you with your compiler (some compilers "help" you by initializing uninitialized variables to 0 when building in debug mode), but did not work for me under GCC.
In external function f, the call "X(2) indeed creates a temporary object.
In ANY CONSTRUCTOR of CLASS X, the call "X(2)" should invoke the CURRENT OBJECT's constructor matching the signature of "X(2)."

If it were to create a TEMPORARY OBJECT, you wouldn't be able to control which base constructors get called in derived classes.

Take a look at this example which comes from this list of C++ Constructor/Destructor TIPS

Note 1: In the aformentioned examples, the term "ctor" is short for constructor, "dtor" for destructor.

Note 2: In the aformentioned example, all constructors being called from other constructors are being invoked from the "initializer list" section of each calling constructor, not the constructor body (i.e. not inside the "{}" of the constructor). Perhaps this makes a difference, but I'm not sure of that.

Here's a simple program which should resolve this debate:

#include <iostream.h>

class X
{
public:
X()
{
cout << "*this() is being constructed:\t" << this << endl;
X(1); // Invoke constructor X(int i) -or- Construct a temporary object X???
}

X(int i)
{
cout << "*this(" << i << ") is being constructed:\t" << this << endl;
}

~X()
{
cout << "*this is being destroyed:\t" << this << endl;
}
};

int main(void)
{
X objX; // Construct a single object X
return 0;
}

If what I'm claiming is correct, the output will be:
*this is being constructed: <address value #1>
*this(1) is being constructed: <address value #1>
*this is being destroyed: <address value #1>

If what you're claiming is correct, the output will be:
*this is being constructed: <address value #1>
*this(1) is being constructed: <address value #2>
*this is being destroyed: <address value #2>
*this is being destroyed: <address value #1>

If the output matches your claim, make the following code change and see if it results in my claim's output:

X() : X(1) // Invoke constructor X(int i) in the initializer list
{
cout << "The address of *this() is: " << this << endl;
}

P.S. If I had a C++ compiler installed, I'd have tested this already. I recently re-formatted and re-installed my OS. As such I haven't gotten around to re-installing a compiler yet.
 

manly

Lifer
Jan 25, 2000
11,685
2,641
136
Originally posted by: TheDiggler
In external function f, the call "X(2) indeed creates a temporary object.
In ANY CONSTRUCTOR of CLASS X, the call "X(2)" should invoke the CURRENT OBJECT's constructor matching the signature of "X(2)."

If it were to create a TEMPORARY OBJECT, you wouldn't be able to control which base constructors get called in derived classes.

Take a look at this example which comes from this list of C++ Constructor/Destructor TIPS

Note 1: In the aformentioned examples, the term "ctor" is short for constructor, "dtor" for destructor.

Note 2: In the aformentioned example, all constructors being called from other constructors are being invoked from the "initializer list" section of each calling constructor, not the constructor body (i.e. not inside the "{}" of the constructor). Perhaps this makes a difference, but I'm not sure of that.
Yes it does make a difference. The initializer syntax is the C++ mechanism for specifying chained constructors (instead of the default). Also, while that link you gave is good, the case for a class hierarchy does not necessarily exemplify the single-class situation. See below.

Here's a simple program which should resolve this debate:

#include <iostream.h>

class X
{
public:
X()
{
cout << "*this() is being constructed:\t" << this << endl;
X(1); // Invoke constructor X(int i) -or- Construct a temporary object X???
}

X(int i)
{
cout << "*this(" << i << ") is being constructed:\t" << this << endl;
}

~X()
{
cout << "*this is being destroyed:\t" << this << endl;
}
};

int main(void)
{
X objX; // Construct a single object X
return 0;
}

If what I'm claiming is correct, the output will be:
*this is being constructed: <address value #1>
*this(1) is being constructed: <address value #1>
*this is being destroyed: <address value #1>

If what you're claiming is correct, the output will be:
*this is being constructed: <address value #1>
*this(1) is being constructed: <address value #2>
*this is being destroyed: <address value #2>
*this is being destroyed: <address value #1>

If the output matches your claim, make the following code change and see if it results in my claim's output:

X() : X(1) // Invoke constructor X(int i) in the initializer list
{
cout << "The address of *this() is: " << this << endl;
X(1);
}
I can confirm that at least with g++, arcain is correct (the second output is emitted). Furthermore, the change you suggested is not valid C++ (and does not compile) as the initializer/constructor syntax apparently applies only to calling a superclass constructor (and not an alternate overloaded constructor in the same class).

So apparently in C++, you don't call an overloaded constructor as you can in Java or C#, but rather you use default argument value(s) as glugglug pointed out.

I had been reading through Stroustrup's C++ Programming Language recently, and when I read arcain's explanation, it made sense and sounded correct based on what I recall reading. But there are just so many subtleties and edge cases in the language that it's easy to get mired on concepts I take for granted coming from a weanie Java world. I definitely learned a couple points from reading this thread and trying your test case.
 

manly

Lifer
Jan 25, 2000
11,685
2,641
136
As another semi-related point, consider the initializer for member fields. There is an important distinction between using the initializer syntax vs. an assignment in the constructor body.

So based on that, it's only logical that there would be a distinction between the initializer syntax for a chained constructor vs. calling a constructor in the body. As it turns out, the former applies only to calling a superclass constructor, and the latter is semantically incorrect.
 

TheDiggler

Senior member
Dec 23, 2002
695
0
0
Yeah, I tried out my sample code on a friend's linux box using g++. It indeed produced arcain's output:
*this() is being constructed: 0xbffffd2b
*this(1) is being constructed: 0xbffffcfb
*this is being destroyed: 0xbffffcfb
*this is being destroyed: 0xbffffd2b

And manly, I got the same error about not invoking a BASE CLASS when trying to call X(1) in the initializer list.

I guess when you stop coding in C++ for over a year, you forget these things. After proving myself wrong, I now recall what I did in the past to work around this "annoyance:"

When I'd need to duplicate functionality in multiple constructors, I'd create a private commonInit() method which could then be invoked from the various constructors.

glitchny, the best solution then for your program is to go w/ glugglug's suggestion:
Remove the DEFAULT CONSTRUCTOR altogether and change StackType(int stackSize) prototype to:
StackType(int stackSize=MAX_ITEMS);

And for the record: I WAS WRONG!
 
sale-70-410-exam    | Exam-200-125-pdf    | we-sale-70-410-exam    | hot-sale-70-410-exam    | Latest-exam-700-603-Dumps    | Dumps-98-363-exams-date    | Certs-200-125-date    | Dumps-300-075-exams-date    | hot-sale-book-C8010-726-book    | Hot-Sale-200-310-Exam    | Exam-Description-200-310-dumps?    | hot-sale-book-200-125-book    | Latest-Updated-300-209-Exam    | Dumps-210-260-exams-date    | Download-200-125-Exam-PDF    | Exam-Description-300-101-dumps    | Certs-300-101-date    | Hot-Sale-300-075-Exam    | Latest-exam-200-125-Dumps    | Exam-Description-200-125-dumps    | Latest-Updated-300-075-Exam    | hot-sale-book-210-260-book    | Dumps-200-901-exams-date    | Certs-200-901-date    | Latest-exam-1Z0-062-Dumps    | Hot-Sale-1Z0-062-Exam    | Certs-CSSLP-date    | 100%-Pass-70-383-Exams    | Latest-JN0-360-real-exam-questions    | 100%-Pass-4A0-100-Real-Exam-Questions    | Dumps-300-135-exams-date    | Passed-200-105-Tech-Exams    | Latest-Updated-200-310-Exam    | Download-300-070-Exam-PDF    | Hot-Sale-JN0-360-Exam    | 100%-Pass-JN0-360-Exams    | 100%-Pass-JN0-360-Real-Exam-Questions    | Dumps-JN0-360-exams-date    | Exam-Description-1Z0-876-dumps    | Latest-exam-1Z0-876-Dumps    | Dumps-HPE0-Y53-exams-date    | 2017-Latest-HPE0-Y53-Exam    | 100%-Pass-HPE0-Y53-Real-Exam-Questions    | Pass-4A0-100-Exam    | Latest-4A0-100-Questions    | Dumps-98-365-exams-date    | 2017-Latest-98-365-Exam    | 100%-Pass-VCS-254-Exams    | 2017-Latest-VCS-273-Exam    | Dumps-200-355-exams-date    | 2017-Latest-300-320-Exam    | Pass-300-101-Exam    | 100%-Pass-300-115-Exams    |
http://www.portvapes.co.uk/    | http://www.portvapes.co.uk/    |