programming2012. 4. 16. 10:31

SetUnhandledExceptionFilter 를 사용하여 이벤트를 후킹하여 미니덤프를 작성 하다보면 스택 오버 플로우는 덤프 사이즈가 0kb 로 남는다.

원인을 생각해 보면, stack 은 thread 별로 할당이 되고, 이미 stack overflow  상태의 thread 에서는 미니덤프를 작성할 수가 없다. 미니덤프를 남기는 함수에서도 stack 을 사용해야 하는데, 더 사용할 공간이 없기 때문이다.

그래서 해결방법은 의외로 간단하다 새로운 thread 를 생성하고 새로 생성된 thread 에서 미니덤프를 작성 하면된다.

 


long __stdcall CrashDump::ExceptionHandler( PEXCEPTION_POINTERS info )
{
	if( info == NULL )
	{	
		return EXCEPTION_EXECUTE_HANDLER;
	}	

	//stack overflow 거 걸리면 스레드 스텍이 다 사용된 것이므로 해당 스레드로는
	//덤프를 남길수가 없다. 그래서 새로 스레드를 생성하여 덤프를 남긴다.
	if(info->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW)
	{
		HANDLE hThread = CreateThread(NULL, 0, WriteDump, info, 0, NULL);
		WaitForSingleObject(hThread, INFINITE);
		CloseHandle(hThread);
	}
	else
	{
		WriteDump(info);
	}		

	return EXCEPTION_EXECUTE_HANDLER;
}

 

WriteDump 는 미니덤프를 만드는 코드가 들어있는 메소드 이다.
Posted by 상현달
programming2012. 2. 1. 17:32

DB 쪽 작업 할 때 마다 찾아보게 되서 한번 정리~

 SQL  C++  최소~최대  타입

정확한 수치
 binint  int64

-2^63 ~ 2^63-1
-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807

 8바이트
 numeric   - 10^38 +1 ~ 10^38 - 1  decimal 과 동일
 bit  bool  0 ~ 1  테이블 내에
1 ~ 8 개면 1바이트
9 ~ 16 개면 2바이트
 smallint  short

-2^15 ~ 2^15-1
-32,768 ~ 32,767

 2바이트
 decimal    - 10^38 +1 ~ 10^38 - 1  numeric 과 동일
 smallmoney  float  - 214,748.3648 ~ 214,748.3647  4바이트
 int  int

-2^31 ~ 2^31-1
-2,147,483,648 ~
2,147,483,647

 4바이트
 tinyint  byte 0 ~ 255  1바이트
 money  double  -922,337,203,685,477.5808 ~ 922,337,203,685,477.5807  8바이트

나머지 데이타들은 바로 매칭 되지 않아 중간에서 적절히 맞춰 주어야 한다.

SQL 데이타 형식 참고 http://msdn.microsoft.com/ko-kr/library/ms187752.aspx
Posted by 상현달
programming2010. 12. 8. 18:06


템플릿 특화(Template specialize)를 이용한 BOOST_STATIC_ASSERT
BOOST_STATIC_ASSERT 은 컴파일 타임에 ASSERT 를 수행한다.
이 기능을 템플릿 특화를 이용하여 간단하게 만들어 본다.

template <bool> class ComplieTimeAssert;
template <> class ComplieTimeAssert<true> {};   //bool 템플릿을 true 만 특화 시킨다.

#define COMPLIETIME_ASSERT(expr) (ComplieTimeAssert<expr>())

void main(void)
{	    
    COMPLIETIME_ASSERT(true);
    //COMPLIETIME_ASSERT(false);
}

COMPLIETIME_ASSERT(true); 가 있을 경우 성공적으로 컴파일 된다.
COMPLIETIME_ASSERT(false); 주석을 풀어서 컴파일 할 경우 다음과 같은 오류 메시지가 발생한다.

error C2514: 'ComplieTimeAssert<__formal>' : 클래스에 생성자가 없습니다.
with
[
__formal=false
]
컴파일 중인 클래스 템플릿 인스턴스화 'ComplieTimeAssert<__formal>'에 대한 참조를 확인하십시오.
with
[
__formal=false
]

템플릿 특화는 이런 용도 보다는 라이브러리 제작시 확장성, 융통성 을 증가시킬수 있다.
그리고 컴파일 타임에 결정이 되므로 빈번하게 연산되는 작업에도 많이 사용한다.


factorial 로직을 함수, 템플릿으로 구현해보면 아래와 같다.
돌일한 결과지만 함수로 만든경우 런타임시 값이 계산 되고, 템플릿으로 구현시 컴파일 타임에 값이 계산된다.

#include "stdafx.h"
#include 

template 
struct factorial
{
	enum {value = n * factorial::value};
};

template<> struct factorial<1>
{
	enum {value = 1};
};

unsigned short factorial_func(unsigned short n)
{
	if(n <= 1) return 1;
	return n * factorial_func(n-1);
}

int _tmain(int argc, _TCHAR* argv[])
{
	std::cout << factorial<4>::value << std::endl;	
	std::cout << factorial_func(4)   << std::endl;	
	return 0;
}

Posted by 상현달
programming2010. 11. 2. 15:27

일반 함수

void main(void)
{
	typedef int(*FUN_POINT_PRINTF)(const char*, ...);

	FUN_POINT_PRINTF _printf = printf;

	_printf("%s world !!!\n", "hello");
	
}

클래스 내에 맴버 함수

class member_func
{
public:
	int func(const char* string)
	{
		return printf(string);
	}
};

void main(void)
{
	typedef int(member_func::*FUN_POINT_PRINTF)(const char*);

	FUN_POINT_PRINTF _func = &member_func::func;

	member_func member_func_obj;
	(member_func_obj.*_func)("hello world !!!\n");
}

함수 포인터를 클래스로 wapper

class wrapper_func
{
	typedef int(*FUN_POINT_PRINTF)(const char*, ...);
public:
	wrapper_func(FUN_POINT_PRINTF func_point_printf) : func_point_printf_(func_point_printf) 
	{}

	int operator() (const char* string)
	{
		return func_point_printf_(string);
	}
private:
	FUN_POINT_PRINTF func_point_printf_;
};

void main(void)
{
	wrapper_func wapper(printf);

	wapper("hello world !!!\n");
}
Posted by 상현달
programming2009. 10. 5. 16:28

먼저 사용 샘플을 사용하는 방법 부터 설명 하겠다. 밑에 놈을 다운 받아 압축 풀고 하나씩 따라해 보삼~



1, test.reg 를 실행 시킨다. 실행시키면 다음과 같이 등록된다.






















이렇게 등록이 되면 인터넷 브라우져가 Navigate 할때 프로토콜이 "test://" 일 경우 추가한 레지스트리의 정보를 참고한다.

2, "Test.exe" 파일을 "C:\\Test.exe" 로 복사한다.
위의 레지스트리 정보에서 실행될 경로를 "C:\\Test.exe" 해 놓았기 때문에~

3, 인터넷 브라우져를 열고 주소창에 "test://babo.htm" 를 입력하고 Navigaet 한다.












4, 아래와 같은 결과가 나타나면 성공








요거 요거 모르고 있던 사실이다. 예전에 브라우져에서 로컬파일을 실행시키기 위해선 모조건 ActiveX 를 만들어서 실행했는데, 외부 프로토콜을 레지스트리에 등록해 주면 요렇게 실행을 시켜준당.

% IE, 크롬에서 테스트 해봤다.
Posted by 상현달