소멸자 호출 오류 도와주세요ㅠㅠ
글쓴이: jo49973477 / 작성시간: 화, 2020/04/28 - 3:15오후
안녕하세요! 오늘도 어김없이 과제에 치여 사는 대학생입니다! 이번에도 지난번과 같이 소멸자가 일찍 나타나는 오류가 일어난 것 같습니다.
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]을 넣고 바로 생성되었다는 것을 알아냈습니다. 사실 다른 오류도 있는 것 같으나 일단 소멸자부터 잡아내야 할 것 같습니다. 현상은 알아냈으나 그 원인은 알 수 없었는데, 왜 이런 일이 발생한 건가요?
코드 풀버전은 하단 압축파일에 있습니다.
Forums:
1. 3의 법칙(law of three)이라는 것이
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++에서는 명시적으로 참조자를 써 줘야 합니다.
댓글 달기