• 카테고리

    질문 & 답변
  • 세부 분야

    게임 프로그래밍

  • 해결 여부

    미해결

함수가 끝나는 시점에서 크래쉬가 나요!

22.12.01 14:57 작성 22.12.01 15:02 수정 조회수 246

0

#include <iostream>

using namespace std;

#include <list>

//양방향 리스트, 링크드 리스트.
template<class T>
class Node {

public:
	Node() : _next(nullptr), _prev(nullptr), _data(T()) {

	}
	Node(const T& value) : _next(nullptr), _prev(nullptr), _data(value)
	{

	}

public:
	Node* _next;
	Node* _prev;
	T _data;
};


template<class T>
class Iterator
{
public:
	Iterator() : _node(nullptr)
	{

	}
	Iterator(Node<T>* data) : _node(data) {

	}

	Iterator<T>& operator++()
	{
		_node = _node->_next;
		return *this;
	}
	Iterator<T> operator++(int)
	{
		Iterator<T> temp = *this;
		_node = _node->_next;
		return temp;
	}

	Iterator<T>& operator--() {
		_node = _node->_prev;
		return *this;
	}
	Iterator<T> operator--(int)
	{
		Iterator<T> temp = *this;
		_node = _node->_prev;
		return temp;
	}
	T& operator*()
	{
		return _node->_data;
	}
	bool operator==(const Iterator& right)
	{
		return _node == right._node;
	}
	bool operator!=(const Iterator& right)
	{
		return !(*this == right);
	}

public:
	Node<T>* _node;
};


//[1]->[2]->[3]->[4]->[header]가 빈 깡통이어도 기본 
template<class T>
class List {

public:
	typedef Iterator<T> iterator;
	List() :_size(0)
	{
		_header = new Node<T>();
		_header->_next = _header;
		_header->_prev = _header;
	}
	~List() {
		//TODO
		while (_size > 0)
			pop_back();

		delete _header;
	}
	void push_back(const T& value)
	{
		AddNode(_header, value);
	}
	// [1] <-> [2] <-> 3 <->[header]
	// [1] <-> [2] <-> [ header ] 
	void pop_back()
	{
		RemoveNode(_header->_prev);
	}
	iterator insert(iterator iter, T _data)
	{
		return iterator(AddNode(iter._node, _data));
	}
	iterator erase(iterator iter)
	{
		Node<T>* target = RemoveNode(iter._node);
		return iterator(target);
	}
private:
	Node<T>* AddNode(Node<T>* before, const int& value)
	{
		Node<T>* newNode = new Node<T>(value);
		Node<T>* prevNode = before->_prev;

		prevNode->_next = newNode;
		newNode->_next = before;

		before->_prev = newNode;
		newNode->_prev = prevNode;

		++_size;
		return newNode;
	}
	Node<T>* RemoveNode(Node<T>* target)
	{
		Node<T>* prevNode = target->_prev;
		Node<T>* nextNode = target->_next;

		prevNode->_next = nextNode;

		nextNode->_prev = prevNode;

		--_size;


		delete target;
		return nextNode;
	}

public:
	iterator begin() { return iterator(_header->_next); }
	iterator end() { return iterator(_header); }

	int size() { return _size; }
public:

	Node<T>* _header;
	int _size;
};

template<class T>
void test(T);
int main() {

	/*List<int> li;
	List<int>::iterator eraseIt;

	for (int i = 0; i < 10; i++)
	{
		if (i == 5) {
			eraseIt = li.insert(li.end(), i);
		}
		else
		{
			li.push_back(i);
		}
	}

	li.pop_back();
	li.erase(eraseIt);
	for (auto i = li.begin(); i != li.end(); ++i)
	{
		cout << *i << endl;
	}*/

	test(List<int>());

}

template<class T>
void test(T) {
	T li;
	T::template iterator eraseIt;

	for (int i = 0; i < 10; i++)
	{
		if (i == 5) {
			eraseIt = li.insert(li.end(), i);
		}
		else
		{
			li.push_back(i);
		}
	}

	li.pop_back();
	li.erase(eraseIt);
	for (auto i = li.begin(); i != li.end(); ++i)
	{
		cout << *i << endl;
	}

}

 

해당 코드에서 main에서 주석으로 처리한 부분은 잘 되는데 template로 작성한 펑션이 끝나면 Invalid address specified to RtlValidateHeap 크래쉬가 나는데 이유가 궁금합니다.. ㅠ

답변 1

답변을 작성해보세요.

1

리스트를 연습용으로 한 것이라 완전하지 않고
operator= 등의 복사에 대한 처리가 안 되어 있습니다.

test(List<int>());
여기서 임시 리스트를 만들어서 복사를 하고 있는데
그럴 경우 기본 헤더와 size 등이 [얕은 복사]로 넘어가서
동일한 헤더를 두 번 지우게 됩니다.

template<class T>
void test(T& li); 로 해서 왼값을 넘기거나
void test(T&& li); 로 해서 오른값을 넘기는 식으로 수정하시면 됩니다.