소멸자 호출 오류 도와주세요ㅠㅠ

jo49973477의 이미지

안녕하세요! 오늘도 어김없이 과제에 치여 사는 대학생입니다! 이번에도 지난번과 같이 소멸자가 일찍 나타나는 오류가 일어난 것 같습니다.

Stack.h

#ifndef STACK_H
#define STACK_H
 
int priority(char oper);
 
#include "Calculator.h"
#include "Stack.h"
 
class Calculator;
 
class Stack {
private:
	char * _stack;
	int _size;
 
public:
	Stack();
	~Stack();
	void putOperator(char input, Calculator cal);
	void putElement(char input);
	void removeElement();
	void ifThereisBlanket(Calculator cal);
	void TomakeStackEmpty(Calculator cal);
 
};
 
#endif // !STACK_H
 
 
#pragma once

Calculator.h

#ifndef CALCULATOR_H
#define CALCULATOR_H
 
#include "Stack.h"
#include "Calculator.h"
 
class Calculator {
private:
	char * _infix;
	char * _postfix;
	int _size_pos;
	Stack stack;
	int _result;
 
public:
	Calculator();
	~Calculator();
	void setInfix();
	void setPostfix();
	char * showPostfix();
	void calculate();
	int getResult();
	void putElement(char input);
 
};
 
#endif // !CALCULATOR_H
 
 
#pragma once

ClassFunctions.h

#include <iostream>
#include <cstring>
#include "Calculator.h"
#include "Stack.h"
 
using namespace std;
 
Calculator::Calculator() {
	_infix = new char[100];
	_postfix = new char[100];
	cout << "생성자 생성\n";
	_size_pos = 0;
}
 
Calculator::~Calculator() {
	delete[] _infix;
	delete[] _postfix;
}
 
void Calculator::setInfix() {
	cout << "수식을 입력하시오: ";
	cin.getline(_infix, 100);
 
}
 
void Calculator::setPostfix() {
	for (int i = 0; i < strlen(_infix) + 1; i++) {
		if (_infix[i] >= '0' && _infix[i] <= '9') {
			this->putElement(_infix[i]);
			cout << "상수 넣음\n";
		}
		else if (_infix[i] == '+' || _infix[i] == '-' || _infix[i] == '*' || _infix[i] == '/' || _infix[i] == '(') {
			this->putElement('|');
			stack.putOperator(_infix[i], *this);
			cout << "연산자 넣음\n";
		}
		else if (_infix[i] == ')') {
			this->putElement('|');
			stack.ifThereisBlanket(*this);
			cout << "닫는괄호 사용함\n";
		}
	}
	cout << "끝내기\n";
	stack.TomakeStackEmpty(*this);
}
 
Stack::~Stack() {
	delete[] _stack;
	cout << "소멸자 호출";
}
 
void Stack::putOperator(char input, Calculator cal) {
	if (this->_size == 0) {
		this->putElement(input);
	}
 
	else if (priority(_stack[this->_size - 1]) < priority(input)) {
		this->putElement(input);
	}
	else {
		cal.putElement(_stack[this->_size - 1]);
		this->removeElement();
		this->putElement(input);
		//stack[_size-1]을 바깥세상으로 탈주시키고 그 자리에 input을 stack[_size-1]에 넣는다.
 
	}
}
 
void Stack::putElement(char input) {
	_stack[_size] = input;
	this->_size++;
}

Main.cpp

#include <iostream>
#include "Calculator.h"
#include "Stack.h"
using namespace std;
 
int main() {
	Calculator calculator;
 
	calculator.setInfix();
	calculator.setPostfix();
	calculator.showPostfix();
 
	return 0;
}

코드는 다음과 같고 디버그 시 "Project9.exe가 중단점을 트리거했습니다."라는 오류가 떴습니다. 결국 Stack 소멸자가 일찍 나타나서 없는 값을 참조하기 때문에 발생한 오류라 생각하고, 소멸자가 생성되는 위치를 잡아내기 위해 소멸자 생성 시 해당 사실을 cout으로 알리게 하였고, 소멸자가 stack에 _infix[0]을 넣고 바로 생성되었다는 것을 알아냈습니다. 사실 다른 오류도 있는 것 같으나 일단 소멸자부터 잡아내야 할 것 같습니다. 현상은 알아냈으나 그 원인은 알 수 없었는데, 왜 이런 일이 발생한 건가요?

코드 풀버전은 하단 압축파일에 있습니다.

File attachments: 
첨부파일 크기
Image icon 에러11.52 KB
Package icon 코드 풀버전2.02 KB
익명 사용자의 이미지

1. 3의 법칙(law of three)이라는 것이 있습니다.

클래스가 non-default (1)복사 생성자, (2)복사 할당 연산자, (3)소멸자 중 하나라도 가진다면
결국 셋 다 non-default여야 한다는 말입니다.

귀하의 코드에서 Calculator와 Stack class는 non-default 소멸자를 가집니다.
따라서 복사 생성자와 복사 할당 연산자도 non-default로 적절히 만들어 주어야 합니다.

아니면 복사를 아예 금지해 버리던지요.

3의 법칙이 왜 지켜져야만 하는지 고찰하는 건 연습 문제로 남기겠습니다.

2. 애초에 문제가 되는 부분은, Stack::putOperator과 같은 함수에서 Calculator를 "값으로" 받아 오는 부분입니다.

위 1번 항목과 관련되어 있는데, 여기서 디폴트로 제공되고 있는 복사 생성자는 적절하지 않습니다.

더군다나 로직 자체도 의심스럽습니다.

Stack과 같은 일반적인 자료 구조를 가리키는 이름을 가진 클래스에 이런 이상한 역할을 부여하는 설계 철학은 둘째치더라도, 왜 메서드에 Calculator에 대한 참조가 아닌 값(복사본)을 전달하나요?

혹시 자바 같은 언어 쓰다가 오셨나요? 자바에서처럼 객체를 참조로 전달하려면 C++에서는 명시적으로 참조자를 써 줘야 합니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.