new 연산시 무한 루프에 빠지는 현상은?

mastercho의 이미지

CPacket 이라는 패킷 구조체를 만들고

new로써 만드는데

처음 만들때는 이상없지만

2번째 만들때는

operator new(unsigned) (sz=256) at ../../../../libstdc++-v3/libsupc++/new_op.cc:46
46      ../../../../libstdc++-v3/libsupc++/new_op.cc: No such file or directory.
        in ../../../../libstdc++-v3/libsupc++/new_op.cc
(gdb) s
48      in ../../../../libstdc++-v3/libsupc++/new_op.cc

여기서 무한루프에 빠져버립니다

왜 그러는지 도데체 알수가 없네요 미치겠습니다 T_T

답변좀 부탁드립니다

mrchu의 이미지

소스코드를 보여주셔야 할것 같은데요.
소스코드가 없이 예측해 본다면 리커시브 콜이 아닌가 의심됩니다만...

mastercho의 이미지

단순한 코드가 아니라 객체에 객체 사이를 오가는 코드라

어케 보여드리긴 힘들거 같고요

단순히 말씀 드리자면

gdb로 추척을 하였기때문에 재귀에 재귀 호출은 분명히 아니고요
[그런 무한 루프가 아니라]

new로 메모리 할당을 한뒤에

다음에 그 쓰레드에서 다시 new를 할 경우 뻣어버리는 증상입니다

위에 코드부분에서 메모리를 100% 먹어버립니다

코드가 진행이 되지 않고요

무슨 말씀인지 이해를 하셨는지요?

new를 왜 썼냐면 한쓰레드에서 다른 쓰레드로 Q클래스를 이용해

자료를 전송하는건데

Q에 자료형은 CPacket 이고 new로 할당해 보내는 역활을 합니다

근데 한번 new 생성후 보낼때는 이상이 없는데

다음 new 생성 코드에서 뻗어버리더라고요

할수 없이 ... new 대신 그냥 버퍼 복사 방식으로 대체 하였지만

버그같다는 생각을 지울수 없네요

승자는 자기보다 우월한 사람을 보면 존경심을 갖고 그로부터 배울 점을 찾지만 패자는 자기보다 우월한 사람을 만나면 질투심을 갖고 어디 구멍난 곳이 없는지 찾는다.
- 하비스

mrchu의 이미지

그래도 소스 없이 설명만으로는 추측밖에 할 수가 없군요.
무한 루프가 아니고, new가 죽어 버린단 말씀이신가요?

그렇담 그 메모리를 쓰는 부분이 할당한 메모리보다 많은 양을 사용하지 않았나 점검해 보세요.
메모리 바운더리에러가 의심됩니다.
소스 없이는 이정도 추측 밖에 할 수 없군요.

saxboy의 이미지

역시 이런 에러는 소스코드가 있으나 없으나 피곤한건 마찬가지겠지요. 말씀하시는 내용으로는 꽤 복잡하게 얽혀 있는 코드일것 같다는 생각이 들고...

C++에서 new를 사용할 때 이런 문제가 생기는 것은 아직 한번도 본 기억이 없습니다만, C에서 malloc() 을 부르자 마자 Seg Fault를 받는 것은 조금 복잡하게 코딩을 해보신 분이라면 누구나 경험하신 현상이지요. 아마 이것과 비슷한 문제가 아닐까 합니다만... :-)

C에서 malloc() 을 부르자 마자 죽어버린다면 백퍼센트(!) malloc 에서 돌려주는 헤더부분을 overwrite 해서 생기는 문제입니다. 메모리 디버거 한두개만 돌려보시면 간단히 찾아내실 수 있습니다. gdb만으로 찾아내기는 굉장히 어렵습니다.
보통 malloc()으로 스트링을 받으면서 뒷부분 1바이트를 잊어버린다거나, array뒤에 포인터를 바로 선언해두었는데, 이 array의 사이즈를 넘겨서 write해버린다거나 하는 경우가 대부분입니다. 바운드체커를 혹시 사용하신다면 help를 꼼꼼히 읽어보세요. 이런 류의 에러에 대해서 자세한 설명과 샘플을 많이 보실 수 있습니다.

처음 코드를 작성하시면서 받은 메모리의 크기와 NULL check를 항상 염두에 두시면 이런 문제는 거의 생기지 않거나 생겨도 아주 간단히 해결할 수 있는 경우가 많습니다.

mpatrol 같은 녀석으로 한번 돌려보세요.

mastercho의 이미지

void Analysis(void* buffer,SOCKET socket)
	{
		CHeader* Header = static_cast<CHeader*>(buffer);
		Protocol CMD;
		
		if(PTYPE_NORMAL == Header->GetType())
		{
			CPacket* packet = static_cast<CPacket*>(buffer);
			const void* Data = packet->GetBody();

			switch(packet->GetCMD())
			{
			case CMD_LOGIN :	
				Process_LogIn((CPB_LogIn*)Data,socket);
				break;
			case CMD_JOIN_MEMBER :
				Process_JoinMember((CPB_JoinMember*)Data,socket);
				break;

이건 받은 패킷을 분석한다음 패킷을 처리하는 부분입니다

그다음 패킷을 분석한다음 처리되는 함수

void Process_JoinMember(CPB_JoinMember* cpb,SOCKET socket)
	{
		//가입 실패
		if(false==Mysql.JoinMember(cpb->GetID(),cpb->GetPassword(),cpb->GetNick(),cpb->GetAge(),cpb->GetSex()))
		{
			SendMakePacket(CMD_CLOSE,socket,"이미 가입되어 있는 ID 입니다");
			return;
		} // if(false==Mysql.JoinMember(cpb->GetID(),cpb->GetPassword(),cpb->GetNick(),cpb->GetAge(),cpb->GetSex()))
		//가입 성공
		SendMakePacket(CMD_CLOSE,socket,"성공적으로 가입하였습니다 , 가입한 ID로 로그인 하십시오");
	}

그리고 거기서 처리한 후에 사용되는 문제의 함수부분

void SendMakePacket(Protocol cmd,SOCKET socket,char* Message=NULL)
	{
		CPacket* packet = new CPacket(cmd);
		CPB_Normal* cpb_Normal = (CPB_Normal*)(packet->GetBody());
		cpb_Normal->SetMessage(Message);
		SendProcess->AddSocket(socket,(char*)packet,sizeof(CPacket));
	}

여기가 문제의 코드입니다

CPacket은 패킷 구조체이고요 256크기를 가집니다
SendProcess는 일종의 패킷을 Send만을 전담하는 쓰레드에서

사용되는 poller입니다

소켓과 버퍼packet 버퍼 크기를 넘기고 있죠 [SendProcess의 AddSocket은 일종의 큐의 push 역활]

여기서 첫번째는 아무 이상이 없지만 2번째 SendMakePacket함수을

호출할때 new CPacket부분에서 뻗어버립니다

위에 말씀 하신 버퍼 크기를 넘는 그런 오류는 범하지 않았고요

세그먼트 폴트도 일어나지 않았습니다

단지

operator new(unsigned) (sz=256) at ../../../../libstdc++-v3/libsupc++/new_op.cc:46 
46      ../../../../libstdc++-v3/libsupc++/new_op.cc: No such file or directory. 
        in ../../../../libstdc++-v3/libsupc++/new_op.cc 
(gdb) s 
48      in ../../../../libstdc++-v3/libsupc++/new_op.cc

이부분에서 CPU 100%먹고 코드가 진행되지 않을뿐입니다

레드헷 8.0에서 동작시키고 있고요

보시면 아시겠지만 new로 할당하는 자체에 문제가 있습니다

승자는 자기보다 우월한 사람을 보면 존경심을 갖고 그로부터 배울 점을 찾지만 패자는 자기보다 우월한 사람을 만나면 질투심을 갖고 어디 구멍난 곳이 없는지 찾는다.
- 하비스

verena의 이미지

mastercho wrote:

void SendMakePacket(Protocol cmd,SOCKET socket,char* Message=NULL)
	{
		CPacket* packet = new CPacket(cmd);
		CPB_Normal* cpb_Normal = (CPB_Normal*)(packet->GetBody());
		cpb_Normal->SetMessage(Message);
		SendProcess->AddSocket(socket,(char*)packet,sizeof(CPacket));
	}

여기가 문제의 코드입니다

CPacket은 패킷 구조체이고요 256크기를 가집니다
SendProcess는 일종의 패킷을 Send만을 전담하는 쓰레드에서

사용되는 poller입니다

소켓과 버퍼packet 버퍼 크기를 넘기고 있죠 [SendProcess의 AddSocket은 일종의 큐의 push 역활]

여기서 첫번째는 아무 이상이 없지만 2번째 SendMakePacket함수을

호출할때 new CPacket부분에서 뻗어버립니다

위에 말씀 하신 버퍼 크기를 넘는 그런 오류는 범하지 않았고요

세그먼트 폴트도 일어나지 않았습니다

단지

operator new(unsigned) (sz=256) at ../../../../libstdc++-v3/libsupc++/new_op.cc:46 
46      ../../../../libstdc++-v3/libsupc++/new_op.cc: No such file or directory. 
        in ../../../../libstdc++-v3/libsupc++/new_op.cc 
(gdb) s 
48      in ../../../../libstdc++-v3/libsupc++/new_op.cc

이부분에서 CPU 100%먹고 코드가 진행되지 않을뿐입니다

레드헷 8.0에서 동작시키고 있고요

보시면 아시겠지만 new로 할당하는 자체에 문제가 있습니다

CPacket의 생성자를 한번 봤으면 합니다... 일단 생성자 부분에서 어떤일들이 일어나는지 파악을 할 필요가 있을것 같네요.

mastercho의 이미지

생성자에서 하는 일을 보여드리겠습니다

나머지는 보안상? 구조자체를 보여드리긴 힘들고요

class CPacket
{
public:
	struct CHeader
	{ 헤더에 필요한 변수들 }
	private:
	public:
		// 초기화
		CHeader(int p_type,int p_size,Protocol p_cmd)
		{
			Init(p_type,p_size,p_cmd);
			ZeroMemory(reserved,PTYPE_NORMAL_RESERVED);
		}
		void Init(int p_type,int p_size,int p_cmd)
		{
			faultlessness=htonl(PTYPE_FAULTLESSNESS); version =htonl(PTYPE_VERSION);
			type=htonl(p_type); size=htonl(p_size); info=0;  cmd=static_cast<Protocol>(htonl(p_cmd));
		}
		//무결성 검사
		bool GetFaultlessness()
		{
		무결성 검사 보안상 생략					}
		int GetVersion() { return ntohl(version);}
		int GetType(){ return ntohl(type);}
		int GetSize(){ return ntohl(size);}
		Protocol GetCMD(){ return static_cast<Protocol>(ntohl(cmd));}
	};
	struct SBody
	{
		char body[PTYPE_NORMAL_BODY_SIZE];
		//초기화
		SBody()
		{ZeroMemory(body,sizeof(body));}
	};

private:
	CHeader packetHeader;
	SBody   packetBody;
public:
	CPacket(Protocol cmd) : packetHeader(PTYPE_NORMAL,sizeof(CPacket),cmd) {}
	CPacket() : packetHeader(PTYPE_NORMAL,sizeof(CPacket),CMD_NORMAL) {}
	// 패킷의 인터페이스
	void HeaderInit(int p_type,int p_size,int p_cmd) { return packetHeader.Init(p_type,p_size,p_cmd);}
//기타 인터페이스 생략

	Protocol GetCMD() { return packetHeader.GetCMD();}
	const char* GetBody(){ return packetBody.body;}
};

보시면 아시겠지만 그냥 일반적인 클래스의 변수 초기화 역활밖에 하고 있질 않습니다

승자는 자기보다 우월한 사람을 보면 존경심을 갖고 그로부터 배울 점을 찾지만 패자는 자기보다 우월한 사람을 만나면 질투심을 갖고 어디 구멍난 곳이 없는지 찾는다.
- 하비스

cdpark의 이미지

CHeader의 Init 함수와 ZeroMemory 함수가 의심되네요. 설마 memset?

mastercho의 이미지

#define ZeroMemory(buffer,bufferSize) memset(buffer,0,bufferSize)

으로 해놓았는데 문제가 되나요?

????

힙에 있는 메모리는 memset를 하면 안되는건지요?

잘 써온거라 힙메모리에도 의심없이 썼는데.....

윈도우에서도 이상이 없었던거 같고요...음 --;

승자는 자기보다 우월한 사람을 보면 존경심을 갖고 그로부터 배울 점을 찾지만 패자는 자기보다 우월한 사람을 만나면 질투심을 갖고 어디 구멍난 곳이 없는지 찾는다.
- 하비스

markboy의 이미지

ZeroMemory(reserved,PTYPE_NORMAL_RESERVED);

에서 reserved와 PTYPE_NORMAL_RESERVED 는 어떻게 되나요?

mastercho의 이미지

PTYPE_NORMAL_RESERVED=40  <- 상수값

원하시는 값
char reserved[PTYPE_NORMAL_RESERVED];
따라서 reserved 라는 공간을 초기화 한것뿐입니다 -_-;

memset을 잘못하면 페이지 폴트가 나야 하는거 같은데

그것도 아닌고....

것참

승자는 자기보다 우월한 사람을 보면 존경심을 갖고 그로부터 배울 점을 찾지만 패자는 자기보다 우월한 사람을 만나면 질투심을 갖고 어디 구멍난 곳이 없는지 찾는다.
- 하비스

markboy의 이미지

혹시 이미 free() 된 포인터를 가지고 다시 free() 하시지는 않나요?

전에 windows 에서 코드를 작성하다가 이미 free() 된 포인터를 가지고 다시 free() 하는 실수를 범한 적이 있는데요, 두번 free() 된 이후 호출되는 임의의 malloc() 에서 에러가 발생했었습니다. :(

pynoos의 이미지

inline이 많을경우 최적화하다가 그런 오류가 날 경우도 있습니다.
그런데 전 주로 internal compiler error가 났지 실행 오류가 난것 같진 않은데...

모든 정의를 inline에서 .cc 로 옮겨 보시던지... 너무 많으면

-fno-default-inline

option을 주어서 해보세요.

참고로 저 옵션을 주면 gdb에서 backtrace 등에 inline 함수로 인한 위치가 이상하게 보이는 일이 일어나지 않습니다.
모든 inline을 정상적인 함수처럼 취급해주니까 좀더 깔끔하죠.
단 최적화의 기대를 할 수 없는 단점이 있지만요.

mastercho의 이미지

뜨끔 했습니다.....

모든 함수가 inline이었는데....

설마 그것때문인가요?

:shock:

벌써 그냥 new 로 하는부분은..... 기존에 버퍼에 복사하는 방식으로

싹악....바꿔버렸는데..... (좀 힘들었습니다 :( )

[좀 급해서 , 이것때문에 언제고 버벅일수가 없는지라 :cry: ]

다시 되는지 테스트 하기가... 힘들듯한... [ 재현하기도 힘들듯 :? ]

-- 추가 -----

전처럼 그냥 비슷하게 코드좀 바꿔봤는데 ...... 재현이 안됩니다

헐헐

근데.... 아까 그 현상은 레드헷 8.0과 한컴 3.0 리눅스에서 똑같이 안되더군요
어째튼 new 쓰기가 불안해서 말씀하신 옵션을 써야 할거 같네요..

그리고 디버깅할때 가끔 줄이 제대로 안보이는 현상이 inline때문에 그런거군요 :oops:

테스트 버전일때는 항상 그 옵션주고 컴파일한다음 테스트 해봐야겠네요

~~~~~~

참 .....위에 말씀에.. 최적화 하다 그럴수 있다고 하셨는데

-g 를 준 디버깅 모드로 컴파일하는데 컴파일러가 최적화 하나요? :?:

승자는 자기보다 우월한 사람을 보면 존경심을 갖고 그로부터 배울 점을 찾지만 패자는 자기보다 우월한 사람을 만나면 질투심을 갖고 어디 구멍난 곳이 없는지 찾는다.
- 하비스

mrchu의 이미지

Protocol이라는 구조는 어떤 것인지요.
Protocol 컨스트럭터 속에서 혹시 CPacket을 사용 하거나 하지 않으신가요?

new CPacket(cmd);

이부분에서 임시 객체가 생성될것 같습니다만...

mastercho의 이미지

mrchu wrote:
Protocol이라는 구조는 어떤 것인지요.
Protocol 컨스트럭터 속에서 혹시 CPacket을 사용 하거나 하지 않으신가요?

new CPacket(cmd);

이부분에서 임시 객체가 생성될것 같습니다만...

enum Protocol {} 입니다 8)

승자는 자기보다 우월한 사람을 보면 존경심을 갖고 그로부터 배울 점을 찾지만 패자는 자기보다 우월한 사람을 만나면 질투심을 갖고 어디 구멍난 곳이 없는지 찾는다.
- 하비스

pynoos의 이미지

mastercho wrote:
참 .....위에 말씀에.. 최적화 하다 그럴수 있다고 하셨는데

-g 를 준 디버깅 모드로 컴파일하는데 컴파일러가 최적화 하나요? :?:

inline이 되는 조건이라하더래도, 어떤 이유로 호출하는 함수에 embedding 할 수 없게 되면,

weak symbol 형태로 들어가는 함수형태로 object가 생성이 됩니다.
또, inline이 제대로 되었는데도 불구하고, compiler가 예상하지 못한 사용방법으로 inline 이 되지 말아야하는경우였다면, 예측불가능할 수 있지요.
inline과 그 예측불가 행동에 대해서는 순전히 경험상 말씀드리는 것이며, 이유는 정확히 알지 못합니다.

저도 STL을 자주사용하는지라 class 안의 inline 함수들 때문에 디버깅이 곤란해져서 debug version에서만 저 option을 씁니다.

그리고, -g 옵션은 최적화와는 상관없는 것으로 아는데요? 단지 디버깅 심볼을 넣을 뿐.
나중에 strip 명령으로 제거할 수 있기 때문에 일단은 -g 를 넣고,
release 할 때 strip 한번 해주는 것으로 -g 를 넣지 않고 compile한 효과를 볼 수 있지요.

cdpark의 이미지

mastercho wrote:

그리고 거기서 처리한 후에 사용되는 문제의 함수부분

void SendMakePacket(Protocol cmd,SOCKET socket,char* Message=NULL)
	{
		CPacket* packet = new CPacket(cmd);
		CPB_Normal* cpb_Normal = (CPB_Normal*)(packet->GetBody());
		cpb_Normal->SetMessage(Message);
		SendProcess->AddSocket(socket,(char*)packet,sizeof(CPacket));
	}

보시면 아시겠지만 new로 할당하는 자체에 문제가 있습니다

문제점이 많아 보이네요. 우선 new 로 할당한 CPacket을 언제 free하나요? 그리고 누가? 또 CPacket * 형을 char * 형으로 강제로 형변환하는데... 안전해 보이지 않습니다.

mastercho의 이미지

[

Quote:
문제점이 많아 보이네요. 우선 new 로 할당한 CPacket을 언제 free하나요? 그리고 누가? 또 CPacket * 형을 char * 형으로 강제로 형변환하는데... 안전해 보이지 않습니다

사실 delete의 문제는 아닐듯 싶습니다

메모리릭으로 이어질 뿐이죠.....

만약 메모리릭이 많아져 그런현상이 일어났다면 모를까

패킷 2번째 날릴때 그런현상이 일어났다는건

delete와는 관련이 없어 보입니다

그리고 delete를 언제 하냐면요

SendProcess에서 패킷의 정보를 table에 보관하고 있다가

테이블에서 정보가 삭제가 소멸자가 호출될때

delete (CPacket*) Data; 로 delete를 합니다

따라서 문제는 없다고 판단이 되네요

승자는 자기보다 우월한 사람을 보면 존경심을 갖고 그로부터 배울 점을 찾지만 패자는 자기보다 우월한 사람을 만나면 질투심을 갖고 어디 구멍난 곳이 없는지 찾는다.
- 하비스

cdpark의 이미지

mastercho wrote:
테이블에서 정보가 삭제가 소멸자가 호출될때

delete (CPacket*) Data; 로 delete를 합니다

따라서 문제는 없다고 판단이 되네요

조각난 소스를 가지고 계속 분석하려니...

Data는 혹시
const void* Data = packet->GetBody();
로 얻은 Data인가요?

위 delete 시에 Data가 new로 할당받은 주소가 아니라면 아주아주아주 심각한 결과를 초래합니다.

mastercho의 이미지

Quote:
위 delete 시에 Data가 new로 할당받은 주소가 아니라면 아주아주아주 심각한 결과를 초래합니다.

쩝 제가 설마 여기에 질문을 올리면서 new로 할당하지 않은 코드를 가지고

delete를 하면서 이런글을 올리겠는지요....

당연히 new하지 않은 메모리를 delete하면 정의 되지 않는 동작이 일어납니다

new와 delete 짝을 맞추지 않아 일어나는 수준의 문제는 아니라고 보네요

승자는 자기보다 우월한 사람을 보면 존경심을 갖고 그로부터 배울 점을 찾지만 패자는 자기보다 우월한 사람을 만나면 질투심을 갖고 어디 구멍난 곳이 없는지 찾는다.
- 하비스

댓글 달기

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