c++牛人来吧,析构函数出错了。

错误信息:
Windows 已在 calc.exe 中触发一个断点。
其原因可能是堆被损坏,这说明 calc.exe 中或它所加载的任何 DLL 中有 Bug。
原因也可能是用户在 calc.exe 具有焦点时按下了 F12。
输出窗口可能提供了更多诊断信息。

源代码:
//Calc.h
#include <iostream>
#include "Stack.cpp"
using namespace std;
extern enum Status;
#ifndef CALC_H_
#define CALC_H_
class Calc
{
private:
char * const line;
Stack<double> * const numstack;
Stack<char> * const oprstack;
double result;
int in(char);
int out(char);
void count(double,char,double);
bool make(void);
public:
Calc(const char * = "1+1",const int = strlen("1+1"));
Calc(const Calc &);
~Calc();
double Result(void)const;
friend ostream & operator << (ostream &,const Calc &);
};
#endif

//Calc.cpp
#include "Calc.h"
Calc::Calc(const char * l,const int n) : numstack (new Stack<double>(50)),oprstack (new Stack<char>(50)),line (new char[n + 1])
{
strncpy(line,l,strlen(line));
line[n] = '\0';
make();
}
Calc::Calc(const Calc & cl) : numstack (new Stack<double>(50)),oprstack (new Stack<char>(50)),line (new char[strlen(cl.line) + 1])
{
strncpy(line,cl.line,strlen(line));
this->numstack->Clear();
oprstack->Clear();
make();
}
Calc::~Calc()
{
delete[] line;
delete[] numstack;
delete[] oprstack;
}
bool Calc::make(void){...}
int Calc::in(char e){...}
int Calc::out(char e){...}
void Calc::count(double a,char opr,double b){...}
double Calc::Result(void)const{...}
//Stack.h
#include <iostream>
using namespace std;
#ifndef STACK_H_
#define STACK_H_
extern enum Status
{
success = 0,
overflow,
underflow
};
template<typename Item>
class Stack
{
private:
Item * stack;
const int size;
int top;
public:
//constructors and other methods
Stack(int s = 10);
Stack(const Stack &);
~Stack();
//functions
inline int ItemCount()const{return top + 1;}
inline bool IsEmpty()const{return (top <= -1);}
inline bool IsFull()const{return (top >= size);}
inline void Clear(){top = -1;}
Status Push(const Item & );
Status Pop(Item &);
Status GetTop(Item &);
};
#endif

//Stack.cpp
#include "Stack.h"

template<typename Item>
Stack<Item>::Stack(int s = 10) : size(s)
{
top = -1;
stack = new Item [size];
}

template<typename Item>
Stack<Item>::Stack(const Stack<Item> & stk):size(stk.size)
{
int i = 0;

if(this->stack != NULL)
delete[] this->stack;
this->stack = new Item [size];
this->top = stk.top;
while (i < this->top + 1)
{
this->stack[i] = stk.stack[i];
}
}

template<typename Item>
Stack<Item>::~Stack()
{
delete[] stack;
}
template<typename Item>
Status Stack<Item>::Push (const Item & im){...}
template<typename Item>
Status Stack<Item>::Pop (Item & im){...}
template<typename Item>
Status Stack<Item>::GetTop (Item & im)

//main.cpp
#include "Calc.h"

int main(void)
{
Calc cl("1+1+1+1+1+1+1",strlen("1+1+1+1+1+1+1"));
cout<<cl.Result();
}

你好!代码问题在这“Calc1::Calc1(const char * l,const int n) : numstack (new Stack1<double>(50)),oprstack (new Stack1<char>(50))
{
m_pline = new char[n + 1];
strncpy(m_pline,l,strlen(l));
m_pline[n] = '\0';
make();
}”,注意,字符串拷贝第三个参数应该是strncpy(m_pline,l,strlen(l));。而你写的构造函数中的两个strncpy(line,l,strlen(line));都错了,由于越界,所以把堆栈破坏了。
另外,再讲代码存在的其他几个问题:
1.例如“#include <iostream>
#include "Stack.cpp"
using namespace std;
extern enum Status;
#ifndef CALC_H_
#define CALC_H_” 其实应该所有文件头宏定义要包含所有文件内容,尽管把包含文件写在外面也不会有错,但是如果该头文件被多次包含,则你写在宏外面的头文件也会做多余的被检测工作。
2.#include "Stack.cpp":包含cpp是什么意思?你要的定义肯定是在头文件里面,即使如果是定义在cpp之中,也不需要包含这个,用external就行,所以规范写法是#include "Stack.h"。
3.我不知道你用的是什么编译器,为何你将Stack的实现与定义分开编译器能通过,事实上,c++标准是模板的实现必须在定义是可见。所以即使你的编译器允许,我也希望你遵循标准,把Stack实现放到头文件。
4.一个编程习惯,你用的Stack类是C++标准保留的,不推荐使用,我们写程序对类,变量和函数的命名要么封装到自己的名字空间,要么一定要注意尽量与已有的区别。
你可以参考如下格式。希望让你得到帮助:
#ifndef CALC_H_
#define CALC_H_

#include <iostream>
#include "Stack.h"
using namespace std;
extern enum Status;

class Calc
{
private:
char * const line;
MyStack<double> * const numstack;
MyStack<char> * const oprstack;
double result;
int in(char);
int out(char);
void count(double,char,double);
bool make(void);
public:
Calc(const char * = "1+1",const int = strlen("1+1"));
Calc(const Calc &);
~Calc();
double Result(void)const;
friend ostream & operator << (ostream &,const Calc &);
};
#endif

//Calc.cpp
#include "Calc.h"

Calc::Calc(const char * l,const int n) : numstack (new MyStack<double>(50)),oprstack (new MyStack<char>(50)),line(new char[n + 1])
{
strncpy(line,l,strlen(l));
line[n] = '\0';
make();
}
Calc::Calc(const Calc & cl) : numstack (new MyStack<double>(50)),oprstack (new MyStack<char>(50)),line (new char[strlen(cl.line) + 1])
{
strncpy(line,cl.line,strlen(line));
this->numstack->Clear();
oprstack->Clear();
make();
}
Calc::~Calc()
{
delete line;
delete numstack;
delete oprstack;
}
bool Calc::make(void){return false;}
int Calc::in(char e){return 0;}
int Calc::out(char e){return 0;}
void Calc::count(double a,char opr,double b){return ;}
double Calc::Result(void)const{return 0;}

//stack.h
#ifndef STACK_H_
#define STACK_H_

extern enum Status
{
success = 0,
overflow,
underflow
};
template<typename Item>
class MyStack
{
private:
Item * stack;
const int size;
int top;
public:
//constructors and other methods
MyStack(int s = 10);
MyStack(const MyStack &);
~MyStack();
//functions
inline int ItemCount()const{return top + 1;}
inline bool IsEmpty()const{return (top <= -1);}
inline bool IsFull()const{return (top >= size);}
inline void Clear(){top = -1;}
Status Push(const Item & );
Status Pop(Item &);
Status GetTop(Item &);
};

template<typename Item>
MyStack<Item>::MyStack(int s = 10) : size(s)
{
top = -1;
stack = new Item [size];
}

template<typename Item>
MyStack<Item>::MyStack(const MyStack<Item> & stk):size(stk.size)
{
int i = 0;

if(this->stack != NULL)
delete[] this->stack;
this->stack = new Item [size];
this->top = stk.top;
while (i < this->top + 1)
{
this->stack[i] = stk.stack[i];
}
}

template<typename Item>
MyStack<Item>::~MyStack()
{
delete[] stack;
}
template<typename Item>
Status MyStack<Item>::Push (const Item & im){return success;}
template<typename Item>
Status MyStack<Item>::Pop (Item & im){return success;}
template<typename Item>
Status MyStack<Item>::GetTop (Item & im){return success;}

#endif

//main.cpp
#include "Calc.h"

int main(void)
{
Calc cl("1+1+1+1+1+1+1",strlen("1+1+1+1+1+1+1"));
cout<<cl.Result();
}追问

我的问题是解决了,不过我发现
delete[] numstack;
delete[] oprstack;
这里也不应该有[],而且,如果在Calc.h中包含Stack.h,则出现链接错误,我查了一下,网上说模板类的实现要包含.cpp才可以。是这样么?

追答

对的。析构函数应该为
Calc::~Calc()
{
delete []line;
delete numstack;
delete oprstack;
}
链接问题:见上面
3.我不知道你用的是什么编译器,为何你将Stack的实现与定义分开编译器能通过,事实上,c++标准是模板的实现必须在定义是可见。所以即使你的编译器允许,我也希望你遵循标准,把Stack实现放到头文件。

温馨提示:答案为网友推荐,仅供参考
第1个回答  2011-03-26
不太懂
第2个回答  2011-03-21
I am completely newbie to C++,
i saw your code like this:

delete[] this->stack; //in Stack.cpp

i don't know whether it's OK or not.

delete[](this->stack); //maybe

and nearly no comments in your code ,i can't catch your mind
on what you wanna to do.追问

i think it is right.when i debug this program,i found there was an problem in Calc::~Calc().
"delete[] line".
i am a freshman major in software.can you speak chinese?

追答

I can't type chinese right now,only english and it's not easy for communication.

I am sorry

追问

oh,do u have qq?i think i can improve my english by communicate with u.my qq:30798124.

本回答被网友采纳
相似回答