new에 대해서 궁금한게 있습니다.

bangkert89의 이미지

서문이 좀 길지만 읽어주시면 감사하겠습니다.^^
지금 EffectiveC++를 보면서 공부하고 있습니다.
메모리 관리 챕터에 보면 memoryPool에 대해서 설명되어 있어
코드를 만들어 보면서 공부하는 중입니다.
아래가 책을 참조해서 만든 코드구여
여러 클래스에서 사용되니까 템플릿으로 바꿔놨습니다.

template<class T>
class Pool
{
public:
	Pool(int BlockSize = 512);
	Pool<T> * InitFreeList();
	void * Alloc(size_t size);
	void Free(void * deadMem, size_t size);
	~Pool();
	void SetBlockSize(int BlockSize);
private:
	union
	{
		T * m_Rep;
		Pool<T> * m_Next;
	};
	static int BLOCK_SIZE;
	static Pool<T> * HeadOfFreeList;
	static Pool<T> * OriginalHead;
};
template<class T>
int Pool<T>::BLOCK_SIZE;
 
template<class T>
Pool<T> * Pool<T>::HeadOfFreeList;
 
template<class T>
Pool<T> * Pool<T>::OriginalHead;
 
template<class T>
Pool<T>::Pool(int BlockSize = 512)
{
	BLOCK_SIZE = BlockSize;
	HeadOfFreeList = NULL;
	OriginalHead = InitFreeList();
}
template<class T>
Pool<T> * Pool<T>::InitFreeList()
{
	Pool<T> * NewBlock = static_cast<Pool<T> *>(::operator new(BLOCK_SIZE * sizeof(Pool<T>)));
	for (int i = 0;i < BLOCK_SIZE-1;++i)
	{
		NewBlock[i].m_Next = &NewBlock[i+1];
	}
	NewBlock[BLOCK_SIZE-1].m_Next = NULL;
	HeadOfFreeList = NewBlock;
	return HeadOfFreeList;
}
 
template<class T>
void * Pool<T>::Alloc(size_t size)
{
	if (size != sizeof(T))
	{
		return ::operator new(size);
	}
 
	Pool<T> * pTemp = HeadOfFreeList;
 
	if (pTemp)
	{
		HeadOfFreeList = pTemp->m_Next;
	}
	else
	{
		pTemp = InitFreeList();
		HeadOfFreeList = pTemp->m_Next;
	}
	return pTemp;
}
 
template<class T>
void Pool<T>::Free(void * deadMem, size_t size)
{
	if (deadMem == NULL)
	{
		return;
	}
	if (size != sizeof(T))
	{
		::operator delete(deadMem);
		return;
	}
	else
	{
		Pool<T> * pTemp = static_cast<Pool<T> *>(deadMem);
		pTemp->m_Next = HeadOfFreeList;
		HeadOfFreeList = pTemp;
	}
}
template<class T>
Pool<T>::~Pool()
{
	::operator delete(OriginalHead);
}
template<class T>
void Pool<T>::SetBlockSize(int BlockSize)
{
	BLOCK_SIZE = BlockSize;
}

코드를 만들고 사용해보니 3가지 문제가 있었는데
1. 메모리주소를 받아서 일일이 형변환을 해줘야한다.
2. 항상 호출할때마다 ClassName(Pool을사용하는 클래스)::operator new(size)를 작성해야한다.
3. 생성자 및 소멸자를 일일이 호출해줘야한다.

그래서 new Type 형식처럼 바꿔보려고 합니다.
new Type형식이 어떤식으로 실행되는지 보기위해
int * temp = new int;에 brake point를 걸고
디버깅해서 따라가보면 ::operator new와 new Type이 똑같이 아래에 함수를 호출하는 겁니다.
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
또한 리턴값도 둘다 void * 형태로 리턴됩니다.
!!!!!!!!여기서 질문!!!!!!!(서문이 좀길죠... ㅠㅠ)
new Type이 코드실행이 종료된 후에 리턴값인 void *를 가지고
어떻게 형변환을 하고 생성자를 호출하는 건가요... 단 한줄의 코드없이.....
또 같은 함수를 호출해서 처리를 하는데 왜 결과가 다른거죠.......

처음 올리는 질문이라.. 정신이없을 겁니다.. 친절한 답변 부탁드립니다^^

kukyakya의 이미지

Effective C++을 공부 중이시라면 아마도 본문에 설명이 되어있지 않던가요?

Type* p = new Type(); 과 같이 사용하실 경우 실제로는 두 단계가 수행되게 됩니다.

Type *p = static_cast<Type*>(::operator new(sizeof(Type))); // 1. 메모리 할당
new (p) Type();                                             // 2. 생성자 호출

따라서 operator ::new()를 오버로딩하실 경우 단계 1의 행동을 오버로딩하시게 되는 것이고, 메모리를 할당하는 작업에 있어서는 타입에 관계없이 할당된 메모리의 위치를 넘겨주는 역할만 수행하면 되니까 void* 로 리턴을 하는 것입니다.

사실 두번째 줄의 replacement new 자체도 메모리를 할당하지 않는 operator이긴 하지만 이해하시는데에는 무리가 없을 것 같습니다.

bangkert89의 이미지

실력자 분이시니까...
내부적으로 형변환이 되고 생성자가 호출되는지는 알겠어요..
근데 Type * p = new Type;여기서 젤먼저 수행하는게
메모리를 void *로 할당하고 리턴해주잖아요
디버그를 해보면 함수가끝나고 메인으로 돌아오거든요..
그후에 void *를 가지고 Type * p = new Type; 처럼
코드한줄없이 어떻게 메인함수에서
형변환을 하고 생성자를 호출하는 거죠...........

글고 ::operator new 나 new Type이나 같은 함수를 호출하는데...
ㅠㅠ 어디서 그런 차이가 발생되는지가 궁굼해서 질문올림니다...

kukyakya의 이미지

언어 자체에 내재된 기능입니다. 보여드린 코드가 라이브러리 어딘가에 구현되어있어 디버거로 확인할 수 있는 것이 아니라, 컴파일러 스스로 저러한 과정을 수행하도록 동작한다고 생각하시면 됩니다.

bangkert89의 이미지

답변 감사합니당 ><

shint의 이미지

이렇게 하면. 비슷하지 않을까 생각됩니다.
데이터 형의 크기를 알면. 접근자가 데이터를 가져 올 수도 있고. 형변환도 가능합니다.

#include <stdio.h>
 
typedef struct DF_ST
{
	int a;
	int b;
}ST;
 
int main(int argc, char* argv[])
{
	//
	int n = 10;
	int * p = NULL;
	p = &n;
	printf("%d\n", *p);			//10
	printf("%d\n", ((int)*p));	//10
 
	//
	ST st;
	st.a = 10;
	st.b = 20;
 
	void* pst = NULL;
	pst = &st;
 
	//pst-> ?? 안됨.
	((ST*)pst)->a = 11;	//됨.
 
	printf("%d %d\n", ((ST*)pst)->a, ((ST*)pst)->b);	//11 20
	return 0;
}

----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

shint의 이미지

.

----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.