반응형

다음과 같이 선언 되어 있다고 가정한다

어떤 .h 파일에서...

class NineTile{
public :

static CRect mTileRect;

static void SetTileRectSize( CRect TileSize ){
mTileRect = TileSize; 
}
}




main.cpp 가 아닌 어느 cpp 파일에서 Ninetile 의 static 함수로 접근하여 멤버변수 static CRect mTileRect;

에 접근하려고 하면  NineTile.cpp 에 static CRect NineTile::mTileRect; 의 멤버 초기화를 쓰면 안되는 경우가

발생한다..,  다른 프로젝트에서 만들어진 Dll 파일을 다른 cpp 에서 읽어들여 사용 하는 경우.

호출은 아래에서와 같이 main 이 아닌 어느 cpp

CRect tempTileRect = CRect(0,0, pMapLayerData->miTileWidth,pMapLayerData->miTileHeight );
NineTile::SetTileRectSize(tempTileRect );





어떤 cpp 파일에서 static 함수를 호출 한 후 nineTile 의 static 멤버에 접근하려면

어느 cpp 위에 CRect NineTile::mTileRect;  의 static 변수 선언 문이 있어야 에러가 나지 않는다...


dll 에서 읽어 온것인지라 static 변수 선언을 양쪽에서 해줘야 하나 ????
 

 
 
 
프로세스간 static 변수 공유
 
dll은 기본적으로 코드 공유를 위한 목적으로 사용됩니다.
즉, dll에서 사용되는 데이터 값은 dll을 사용하는 애플리케이션 간에 공유되지 않죠.

예를 들어, dll 안에 static int g_nCount = 0; 라는 값이 있을 때, 
dll에서 export하는 Increase라는 함수를 호출하면 g_nCount++; 라는 구문이 실행되고, g_nCount 값을 리턴한다고 가정하죠.

이 때, 서로 다른 2개의 애플리케이션(즉, 프로세스)에서 
이 dll을 로딩하고 Increase를 호출하면 g_nCount 값은
각각의 프로세스에서 증가되고 모두 1이 리턴됩니다.

즉, 처음에 말한 바와 같이 dll 내에서 static으로 선언한다고 해서
이 변수가 dll을 사용하는 프로세스 간에 공유되지는 않습니다.
그러나 변수 값을 공유하는 방법이 있습니다.

pragma directive를 사용하면 되는데
공유하고자 하는 변수를 

#pragma data_seg(".ioshare")
static int g_nCount = 0;
#pragma data_seg()

위와 같이 data_seg pragma directive 안에 넣어줍니다.
이 때 .ioshare 라는 문자열은
dll 내에 어떤 데이터 영역으로 표시되는지를 결정합니다.
지정하지 않으면 기본적으로 .data 영역에 들어가게 되죠.
(Windows PE 포맷의 기본 데이터 영역입니다.)

프로세스간 데이터 공유에 대해서는 다양한 IPC 방법이 있지만
dll을 사용해서 이렇게도 할 수 있다는 것을 기억하면 좋겠죠. ^^




반응형
반응형

[출처] 멤버 함수를 쓰레드 함수로 만들기.|

멤버 함수를 쓰레드 함수로 만들기.

오늘은 간단한 C++ 프로그래밍 기법에 대해 하나 써볼까 합니다.

간단한 기교를 부려볼 겸 클래스의 멤버함수를 쓰레드 함수로 작성하는 방법을 배워 보도록 하겠습니다.

(간단히 쓰레드 사용법도 배우고 일석이조! 야호! )

아직까진 그런 적은 없지만, 쓰레드를 돌릴 때 간간히 멤버함수를 쓰레드 함수로 제작하고플 때가 있더군요.

혹, 그런 분들을 위해 알려 드리겠습니다.

class TestClass {

INT B;

VOID TestFunction( INT A ) { B = A }; //이 함수를 쓰레드로 돌리고자 합니다.

VOID Start(); //이 함수에서 TestFunction을 호출하지요.

};

Start() 멤버 함수에서 TestFunction()을 쓰레드로 돌리고자 한다고 해보죠.

VOID TestClass ::Start() {

HANDLE hThread = ( HANDLE ) __beginthread( NULL, 0, &TestFunction, NULL, NULL, NULL );

// ........ 무엇가의 작업을 하고.

WaitForSingleObject( hThread, INFINITE );

CloseHandle( hThread );

}

물론 안됩니다. 쓰레드로 돌아갈 함수는 정적으로 선언되어야 하며 정적 함수여야 하죠. 따라서,

class TestClass {

static VOID WINAPI TestFunction( INT A ); // 이제 원래 의도대로 이 함수를 정적 함수로 제작합니다.

VOID Start();

};

역시 물론 안됩니다. 직접 닥쳐보시면 알겠지만, 우리가 돌리고자 했던 TestFunction 함수에서는 B라는 비정적 멤버를 참조하고 있습니다.

결국은 다른 방법을 찾아야 합니다.

class TestClass {

VOID TestFunction( INT A ); //다시 원래대로 돌리고

static VOID WINAPI TestFunctionThread( LPVOID ); //대신 쓰레드가 돌아갈 정적 함수를 만듭니다.

VOID Start();

};

VOID Start() {

HANDLE hThread = ( HANDLE ) __beginthread( NULL, 0, &TestFunctionThread, this, NULL, NULL );

// ........ 무엇가의 작업을 하고.

WaitForSingleObject( hThread, INFINITE );

CloseHandle( hThread );

}

VOID WINAPI TestFunctionThread( LPVOID p ) {

( (TestClass* ) p )->TestFunction( 3 );

}

자, 위 예를 통해 해결했습니다. 포인터. 즉 동적 호출을 통해서 정적 멤버 함수를 호출하였습니다.

TestFunction의 인자 값도 동적으로 주고 싶다면,

struct Arg {

TestClass* p;

INT A;

};

VOID Start() {

Arg arg = { this, 3 };

HANDLE hThread = ( HANDLE ) __beginthread( NULL, 0, &TestFunctionThread, &arg, NULL, NULL );

// ........ 무엇가의 작업을 하고.

WaitForSingleObject( hThread, INFINITE );

CloseHandle( hThread );

}

VOID WINAPI TestFunctionThread( LPVOID p ) {

Arg* pArg = ( Arg* ) p;

pArg->p->TestFunction( p->A );

}

반응형
반응형

[Win API] 스레드 강좌 + CreateThread() 와 _beginthreadex() 함수의 차이 ★ 윈도우 Prog

2008/07/16 16:38

복사 http://blog.naver.com/kaltznnnyyy/140053695650




안녕하세요.

정말 오랫만의 포스팅입니다.

요새 이것저것 노느라 하느라 바빠서 공부와는 거리를 멀리하다가

다시 마음을 살짝 먹고, 글을 쓰고자 이렇게 달려왔습니다

(..라고 해봤자 계속 컴퓨터 앞입니다.)

이번에는 멀티스레드 관련해서 하나 이야기해보고 같이 실험을 해볼까합니다.

기본적으로 프로그램을 실행하게 되면 적어도 1개의 프로세스와 1개의 스레드를

생성하게 되는데, 그 1개의 스레드는 우리가 흔히 알고 있고 작성하고 있는

메인 스레드 ( Console일 경우 main() 함수로 호출 , Win32일 경우 WinMain() 함수로 호출 )

입니다. 메인 함수를 호출하게 되면 시스템 함수에 의해서 한개의 메인 스레드가 생성되는 것이죠.

멀티 스레드란 , 한 프로세스 내에서 메인스레드를 제외한 다른 스레드가 생성되고

돌아가고 있는 것을 말합니다. 한 프로세스 내에서 작업을 나눠서 할 수 있도록 도와주는

녀석이라고나 할까요. 그렇다고 절대 '동시'에 실행되는 것은 아닙니다. 엄청나게 빠르게

스레드 전환 이란 작업이 일어나고 있는 것 뿐이죠. 물론 프로세스도 동시에 실행되는 것이

아니라 프로세스간의 컨텍스트 스위칭 이란 작업이 빠르게 이루어지고 있는 것입니다. 이 작업이 프로그램을 동시에 돌아가도록 착각하게 만드는 것이죠.

멀티 스레드 관련이나 네트워크 관련이 아니고서는 대부분의 C, C++ 강좌 서적에는

이러한 부분에 대하여 자세하게 기술되어있지 않지요. ( 뭐 해봤자 머리만 아플테니... )

하지만 멀티스레드를 조금이라도 정확히 알고 싶으신 분이라면 한번쯤 이 글을 읽어보시는 것도

도움이 되리라 생각되는군요.

자 그러면 일단 스레드라는 녀석을 가볍게 살펴보도록 하겠습니다.

위 그림을 보시면 g_iData 라는 전역변수가 존재합니다.

저는 저 전역변수를 반복분을 통해서 증가시키면서 출력을 시키려고 합니다.

단, 멀티스레드를 사용하기로 하였으므로 증가를 시킬때 두 스레드로 나누어서

증가를 시켜보도록 하겠습니다.

( 뭐 멀티스레드의 장점을 설명하기에 적당한 예제는 아님을 미리 알려드립니다.^^

가장 이해하기 쉽도록 최대한 단순하게 만들었습니다.)

메인 스레드 이외에 다른 2개의 스레드를 생성하고 싶으면 CreateThread란 함수를 사용합니다.

일단 CreateThread 함수의 스펙을 살펴보도록 하죠.

첫 번째 인자는 보안 관련 인자인데, 특별한 처리가 아닌이상 NULL로 지정하시면 됩니다.

두번째는 스레드에 할당할 스택 사이즈인데 0을 인자로 넘기면 디폴트 사이즈가 지정됩니다.

중요한건 세번째 , 네번째 인자인데,

세번째 인자는 스레드 함수의 주소(포인터)를 넘겨줍니다. 함수의 주소는 그 함수의 이름과 같은 건 알고 계시다고 가정하겠습니다. 그런데 그 함수의 기본 모형은 아무렇게나 주어도 되는것인가?

절대 아닙니다. 이 스레드는 유저가 관리하는 영역이 아닌, 시스템이 관리하는 영역이기 때문에

정해진 함수의 원형에 맞게 작성을 해야 시스템이 올바르게 읽고 판단합니다.

넘겨야하는 함수의 원형은 아래와 같습니다.

DWORD WINAPI ThreadProc(LPVOID lpParameter);

인자는 LPVOID 타입인데 , LPVOID는 다시 풀어쓰면 Long Pointer void (void *) 형입니다.

그러므로 4byte 주소를 넘겨줄 수 있는 것이죠. 리턴으로 넘겨주는 DWORD 형은 종료코드이구요.

그러면 질문이 생길 수도 있습니다.

"헉! 거대한 프로그램에서 인자 하나 가지고 어떻게 여러개의 변수를 처리하나요?

스레드 이거 너무 비효율적 아닌가요?"

라고 말이죠. 하지만 조금만 생각을 달리하면 아주 쉽게 응용이 가능합니다. 나중에 아래에서 다시 설명을 드리겠습니다.

네번째 인자는 바로 위 스레드 함수에 넘겨야할 인자를 적어주시면 됩니다.

다섯번째 인자도 그냥 비워두시면 되구요 ( 무조건은 아니지만 지금 단계에서는 필요 없어요 )

여섯번째 인자에는 스레드의 ID 번호를 저장할 DWORD 자료형의 주소를 넘깁니다.

이 스레드 ID번호는 다른 프로세스간 통신 등을 할 때 필요합니다.

( 이 함수가 넘겨주는 HANDLE 은 동일 프로세스 내에서만 유효합니다. )

이 함수를 호출하게 되면 이 스레드를 제어할 수 있는 HANDLE을 리턴하게 되는데,

스레드가 제대로 생성되지 않았을 경우에는 NULL을 리턴하게 됩니다.

자, 말이 길어졌는데 그럼 위 설명을 토대로 간단한 멀티스레드 프로그램을 작성하도록 하겠습니다.

위와 같이 작성을 하게 되면 어떠한 결과가 나올까요? 예상해보시고 아래 답을 봐주세요.

생각과는 다르게 처참한 결과라는 생각이 드시는 분들도 있으실 겁니다.

까무잡잡한 화면에 아무것도 출력되지 않다니요!! 헝헝헝..ㅠ

이런 결과가 생기는 이유는 "메인 스레드는 추가로 생성된 스레드의 종료를 기다리지 않는다"는

것에 있습니다. 다시 말해 ThreadFunc 함수가 호출되어서 실행이 되려는 순간 메인 스레드에서는 할일이 전혀 없었으므로 바로 끝나게 되는데, 메인스레드가 끝나면 모든 프로그램을 종료가 되기 때문에

ThreadFunc 함수 내부의 구문은 실행되지 못한 채 종료가 되어버리는 것입니다.

얼래... 그러면 메인에서 추가된 스레드가 돌아가도록 한 1초정도만 기다리게 해보는건 어떨까요?

CreateThread 함수를 호출한 다음에 Sleep(1000); 을 적고 다시 실행시켜보도록 하죠.

그러면 아래와 같은 정답 비스무리한 결과(?!!)가 나오게 됩니다.

오오... 이제 제대로 돌아가는 군요.... 라고 안심하면 절!대! 안됩니다 ㅎㅎ

일단 첫번째 문제점은 호출한 스레드가 처리하는 동작이 몇초가 걸리는지 몇분이 걸리는지,

아니면 지속적으로 유지가 되는지 전~~혀 알 길이 없기때문입니다. 위 코드는

for문 30번 도는 일이 1초안에는 끝난다고 확신했기 때문에 가능했던 것이지요.

두번째 문제점은 중간에 Sleep으로 오랜시간 스레드를 잠재우면

도스 프로그램 같은 경우에는 해당이 안되지만 윈도우 환경에서 다수의 프로그램이

동시에 돌아갈 때, 다른 프로그램으로의 컨텍스트 스위칭이 이루어지지 않게되는 문제가

생겨버리는 것이지요.

흠...그렇다면 방법이 없는것인가?! ㅎㅎ 아닙니다. 아주아주 친절하게

적절한(김대기...죄송;ㅅ;) 함수를 제공합니다. 바로!!

위 함수의 첫번째 인자에 스레드의 핸들을 넘겨주고 , 두번째 인자에 대기 시간(밀리초)을 넘겨주면

그 스레드가 종료될 때까지 대기를 하게 됩니다. 그럼 이 함수를 적용한 코드를 보도록 하죠.^^

Sleep 함수 대신에 WaitForSingleObject() 함수를 호출합니다. 두번째 인자에 넘겨준

INFINITE는 0xffffffff 로 정의 되어있는 정의문으로 , 스레드가 끝날때까지 무조건 계~~속

기다린다는 의미입니다. ThreadFunc 함수가 종료코드를 반환하기 전까지는 그 다음줄을

실행하는 것을 절대 허락하지 않는것이죠.

자 이제 다시 돌려보겠습니다.

오호! 이것이 원하는 결과입니다! 뭔가 코드가 깔끔하네요.

자 그럼 스레드 끝!

.

.

.

이라고 하면 말도 안되겠죠 ㅋㄷ 이제 시작입니다.

지금까지는 g_iData 변수를 증가시키는 스레드가 1개였죠? 이제 그 작업을 2스레드가

나눠서 해보겠습니다.

위 소스코드를 아래와 같이 적당히 바꿔보지요-

어떤 결과가 나올 것 같나요?^ㅅ^

쉽게 예상하실 수 있겠죠??

그럼 예상해보시고 밑의 결과를 봐주세요~

뭔가 콰지직 쿵! 하는 느낌 안드세요?! 헉헉헉...

저..절대 원하는 결과가 아닙니다. (위 결과는 여러 상황에 따라서 바뀌게 됩니다.)

1부터 30까지 차례대로 출력해주었으면 했다구요!!!그렇죠?

위와 같은 결과는 두 스레드가 동시에 콘솔창에 출력을 행하려고 하기 때문에 일어나게 됩니다.

(위에서도 말했지만 엄밀히 말하면 동시는 아닙니다).

사실 문제는 이 뿐만이 아닙니다. 위 코드는 g_iData에 접근하고 증가시키는데 걸리는 시간이

아주 짧기 때문에 두 스레드간의 처리가 우연히 겹치지 않은 것 뿐이고,

컴퓨터가 아주 느리다면 30이 아닌 엉뚱한 결과가 나올 가능성이 충분히 있는 코드라는 점이죠.

이러한 문제를 해결하기 위해서는 스레드 간에 동기화를 해주어야 합니다.

멀티 스레드 프로그램을 작성하기 위해서는 반드시 반드시 꼭 꼭 알아야할 개념이죠.

(다시 부족전쟁 하고 나서 이어씁니다)


반응형
반응형

 dll 로 만든 헤더를 A에서 dll 함수를 호출하면서 인자로 A 의 멤버 포인터를 넘긴다음

dll 안에서 A 의 함수를 접근하려할때 오류가 난다

원인 : dll 안에서 A 로 접근 할 수 있는 함수의 주소를 알 수 없다

+ 헤더파일에 선언된 함수 즉 inline 함수는 dllexport 할 필요가 없다

반응형
반응형

http://fendee.egloos.com/2230359



응용 프로그램 구성이 올바르지 않기 때문에 이 응용 프로그램을 시작하지 못했습니다VC++(2005)

원 제목: 응용 프로그램 구성이 올바르지 않기 때문에 이 응용 프로그램을 시작하지 못했습니다
"응용 프로그램 구성이 올바르지 않기 때문에 이 응용 프로그램을 시작하지 못했습니다"
실행파일을 실행했을때, 위와같은 에러가 발생했다면,


이런 오류가 발생했을때.
물론, 갖가지 상황들이 있을 수 있으므로, 만병 통치약은 아니겠지만,
내가 접한 이 오류에 대한 분석내용을 올린다.
Visual Studio C++ 2005 가 설치되어 있는 Windows XP pro 에서 만들어진 실행파일(콘솔응용)을
아무것도 설치되지 않은(.Net Framework, C++ Runtime) Windows XP pro 에서 실행했을때,
위와같은 에러를 만나게 되었다.
여러가지 상황에서 테스트를 해보았는데,
결론은 이러하다.
여러가지 상황테스트.
.Net Framework 만 설치하고 실행시켰을때, C++ Runtime 만 설치하고 실행시켰을때, 두가지 모두 설치하고 실행시켰을때,
그러나, 모두 에러가 발생했다.
그래서, 웹서핑도 해보고, 이것저것 해본결과.
우선, 내 경우는, debug 모드로 만들어진 실행파일이었다.
아래의 위치로 들어가보면,
C:\Program Files\Microsoft Visual Studio 8\VC\redist\x86\Microsoft.VC80.CRT (Visual Studio 2005의 경우)
C:\Program Files\Microsoft Visual Studio 9.0\VC\redist\x86\Microsoft.VC90.CRT (Visual Studio 2008의 경우)
내경우에는 Visual Studio 2005 이어서 이것을 기준으로 설명하겠다.
그 폴더에는 아래의 4개 파일이 있다.
Microsoft.VC80.CRT.manifest
msvcm80.dll
msvcp80.dll
msvcr80.dll
이 파일을 실행파일과 같은 폴더에 위치시키면 된다.
그런데, 문제는 그리 간단하지 않다.
위의 파일은 Release 모드로 만들어진 실행파일의 경우 필요한 파일이다.
만약, Debug 모드로 만들어진 실행파일이라면 아래의 파일이 있어야 한다.
C:\Program Files\Microsoft Visual Studio 8\VC\redist\Debug_NonRedist\x86\Microsoft.VC80.DebugCRT (Visual Studio 2005의 경우)
폴더안에 아래의 4개 파일이 있다.
Microsoft.VC80.DebugCRT.manifest
msvcm80d.dll
msvcp80d.dll
msvcr80d.dll
즉, 이 파일들이 없어서 에러가 났다는 것이다.
다시한번 주의하자, Debug 모드로 실행파일을 만든경우와, Release 모드로 실행파일을 만든경우 실행파일과 같이 넣어줘야할 파일이 틀리다.
보면, 디버그모드(Debug) 의 파일들에는 Debug 가 붙거나, 파일이름에 d 가 붙어 있다.
자신이 만든 실행파일이 어떤 모드에서 만들었는지 잘 기억했다가 필요한 파일로 첨부시키면 된다.
그런데, 한가지 재미있는 점은,
만약, Release 모드로 실행파일을 만들었다면, C++ Runtime 가 컴퓨터에 깔려있으면, 위의 파일들을 첨부하지 않아도 된다는 것이다.
Debug 모드로 만든경우에는 C++ Runtime 가 설치되어 있어도 에러가 난다.
그러나, 내가 만든 실행파일은, 정말 기초적인 코딩들만 들어있었다.
그런데도, C++ Runtime 를 필요로 했다면, 이건 정말 기막힐 노릇이다.
항상 프로그램을 누군가에게 주기전에 C++ Runtime 를 먼저 설치하라고 해야 한다는 말인데,
누가 그걸 설치하겠는가.
결국, 그냥 Release 모드로 만든후, dll 파일과 manifest 파일(총4개)을 실행파일과 함께 주는법 밖에는 없다는 결론이다.
정말 지극히도 단순한 코딩인데도 말이다.(Debug 모드로 만든경우에는 48kbyte 이고, Release 모드로 만든경우에는 5kbyte 밖에 안되는데도 말이다)
더 황당한것은, .Net Framework 2.0 을 설치했는데도 에러가 났다는 것이다.

그리고, 위에서 말한 폴더들을 왔다갔다 하다보면,
그 폴더만 있는게 아니고,
Debug 관련 폴더의 경우,
Microsoft.VC80.DebugMFC 폴더, Micorosft.VC80.DebugOpenMP 폴더가 있고,
Release 관련 폴더의 경우,
Microsoft.VC80.ATL 폴더, Microsoft.VC80.MFC 폴더, Microsoft.VC80.MFCLOC 폴더, Microsoft.VC80.OPENMP 폴더가 있는데,
만약, 코딩에서 MFC 를 사용했다거나, 기타 다른 것들을 사용했다면, 각 폴더안의 파일들도 같이 넣어줘야한다.
테스트결과, MFC 를 이용한 실행파일은 CRT 와 MFC 관련 폴더안에 있던 파일들을 모두 넣어줘야 에러가 나지 않았다.
하여간, 뭐가 이리 복잡한겐가.
TurboC++ 3.1(win) 에서 만든 실행파일은 기냥 돌아가더구만.
Visual Basic 의 경우에도, dll 파일을 같이 동봉해야 하는 경우가 많아 이런 에러를 만날일이 많을것이다.
듣기로는 델파이의 경우, 아예 실행파일에 dll 내용을 첨부한다던데,
물론, 그렇게 하면 실행파일의 덩치가 커지는 문제점도 있지만, 이와같이 배포시 문제점은 완벽히 해결되지 않을까?



<Visual Studio> 응용프로그램 구성이 올바르지 않기 때문에 이 응용 프로그램을 시작하지 못했습니다. 해결방법 낙서장

2010/08/27 19:14

복사http://blog.naver.com/myrandy1/80114297241

VS2005 이후로는 제작한 프로그램을 VS가 설치되지 않은 PC에서 실행할 경우

구성이 잘못되어 응용프로그램이 실행되지 않는다는 에러가 뜨면서 실행되지 않는다.

이유는 런타임 라이브러리를 exe파일에 내재하지 않고 dll파일을 이용하여 참조하기 때문에

dll파일이 없거나 그 버젼이 다를 경우 에러가 발생된다.

몇 시간의 삽질 끝에 드디어 위의 문제를 해결할 수 있는 방법을 알아냈다.

1. 일반적으로 인터넷에 나온 방법은 다음과 같다.

C:\Program Files\Microsoft Visual Studio 9.0\VC\redist

C:\Program Files\Microsoft Visual Studio 8\VC\redist

를 보면, 재배포 정보들이 있는데

릴리즈 모드로 빌드된 프로그램은 x86, 디버그 모드로 빌드된 프로그램은 Debug_NonRedist폴더 에 들어있다.

예로 든 실행exe파일은 디버그 모드로 빌드된 프로그램이므로

C:\Program Files\Microsoft Visual Studio 8\VC\redist\Debug_NonRedist\x86\Microsoft.VC80.DebugCRT

C:\Program Files\Microsoft Visual Studio 9.0\VC\redist\Debug_NonRedist\x86\Microsoft.VC90.DebugCRT

에 있는 파일들을 실행exe파일과 같이 배포하면 된다.

배포해야 하는 파일에는 다음과 같은 것들이 있다.

Microsoft.VC90(VC80).DebugCRT.manifest

msvcm90(80)d.dll

msvcp90(80)d.dll

msvcr90(80)d.dll

2. 하지만 실행이 되지 않았다. 보통 인터넷에 나와있는 설명에는 버전에 대한 설명이 없어서 정말 많이 해멨다...

실행파일이 요구하는 dll파일의 버젼을 알아내는 방법은 다음과 같다.

Visual Studio의 File -> Open -> File -> 실행 exe파일로 열면 메니페스트 디펜던시 정보를 얻을 수 있는데..

메니페스트 정보를 더블 클릭하면 디펜던시 정보가 hex파일로 나온다.

이를 마우스로 긁어서 메모판에 붙여 넣기를 하면 메니페스트 정보를 확인할 수 있다.

癤??xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
</requestedPrivileges>
</security>
</trustInfo>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.VC90.DebugCRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
</dependentAssembly>
</dependency>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.VC80.DebugCRT" version="8.0.50727.762" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
</dependentAssembly>
</dependency>
</assembly>

해당 실행파일이 필요로 하는 정보는 Microsoft.VC90.DebugCRT (9.0.21022.8), Microsoft.VC80.DebugCRT (8.0.50727.762)임을 알았다.

하지만, C:\Program Files\Microsoft Visual Studio 9.0\VC\redist\Debug_NonRedist\x86\Microsoft.VC90.DebugCRT

에 있는 dll 파일들의 버젼을 확인해보니까 9.0.30729.1였다. 알고보니 dll파일의 버젼이 하나라도 다르면 실행이 안되는 것이었다.

우리가 필요한 dll버젼은 9.0.21022.8 이기 때문이 이를 찾아야 한다.

이는 C:\Windows\winsxs 에서 찾을 수 있다.

엄청나게 많은 폴더들이 있는데, 잘 찾아보면

x86_microsoft.vc90.debugcrt_1fc8b3b9a1e18e3b_9.0.21022.8_none_96748342450f6aa2 란 이름의 폴더가 있는 것을 볼 수 있다.

이를 열어보면 우리가 찾는 9.0.21022.8 버젼의 dll파일들이 있음을 알 수 있다.

dll의 버젼이 9.0.21022.8이므로 Microsoft.VC90.DebugCRT.manifest 파일도 수정돼야 한다.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<noInheritable></noInheritable>
<assemblyIdentity type="win32" name="Microsoft.VC90.DebugCRT" version="9.0.30729.1" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
....

버젼이 9.0.30729.1로 되어 있으므로 이를 9.0.21022.8로 고친다.

이렇게 해서 고친 매니페스트 파일과 런타임 dll을 실행exe파일과 함께 배포하면....

VS가 설치되지 않은 PC 에서도 잘 동작함을 볼 수 있다.

요약하면, 실행exe파일과 함께 배포해야 하는 파일은

Microsoft.VC90(VC80).DebugCRT.manifest

msvcm90(80)d.dll

msvcp90(80)d.dll

msvcr90(80)d.dll

인데, dll의 버젼과 manifest파일에 명시된 버젼과 실행 exe파일이 요구하는 dll의 버전이 모두 일치해야 한다는 것이다.


http://blog.naver.com/drvoss/20048402862

Dependency Walker : http://www.dependencywalker.com/

오늘 세미나에서 VS2008, 혹은 VS2008 feature pack에 있는 DLL들을 같이 배포 해야 하는가 라는 질문을 받았습니다. 아마도 클라이언트 PC에 2005로 컴파일된 바이너리와 2005 재배포패키지에 있는 DLL파일이 이미 배포되어 있는 상태이셨던것 같습니다.

어플리케이션은 빌드 당시에 물었었던 DLL로 링크가 됩니다. 메니페스트 파일에 이러한 내용들이 링크타임에 기술이 되게 되며,운영체제에서는 이것들을 DLL 버전등에 기반한 side by side로 관리를 합니다.

Windows 폴더에 가보시면 WinSxS 라는 폴더가 존재 하는데, 이 폴더에 보시면 같은 파일들이 각 버전별로 서로 분리가 되어 있습니다. 처음 보시는 분들은 시스템에 따라 엄청나게 많은 폴더에 있는 같은 파일에 당황스러우실 껍니다.

Side by side를 고려 하지 않으면, 보통 exe파일과 같은 폴더에 있는 DLL을 사용할 것이라 잘못 생각할 수 있습니다.

Dependency Walker exe 파일을 열면 아래와 같이 exe 파일이 물고 있는 DLL들의 목록이 보여 집니다.

여기서 F9를 눌러 보면 각 DLL 들의 Full Path가 나오게 됩니다.

아래 그림에서 보시는 것처럼 ALZip.exe은 커먼컨트롤 DLL winsxs 폴더에 저 경로의 것을 사용합니다. ALZip.exe가 있는 폴더에 다른 버전의 같은 DLL 파일을 복사해도 ALZip.exe winsxs에 있는 DLL 파일을 이용할 껍니다.

제 컴퓨터에는 아래의 두개의 경로에 같은 커먼컨트롤DLL 파일이 존재 합니다.

C:\Windows\winsxs\x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82.6000.16386_none_87e0cb09378714f1

C:\Windows\winsxs\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.6000.16386_none_5d07289e07e1d100

디펜즈에서 보시는 것 처럼 첫번째 것을 사용하고 있는데, 두번째 것을 ALZip.exe와 같은 경로로 복사를 해도 여전히 winsxs 폴더에 것을 사용하고 있음을 확인하실 수 있습니다.

exe파일의 경우 자신이 링킹될 때 참고된 DLL에 대한 메니페스트를 가지고 있고, 나중에나중에 될 때 가장 우선으로 자신이 링킹될 때 참고한 DLLside by side에서 선택합니다. 맞지 않는 DLL을 참고할경우 윈도 제어판 이벤트로그에 워닝이 남습니다.

이번 VS2008에서 side by side정보가 변경되었습니다. 따라서, dll 파일을 같이 배포해 주셔야 맞습니다.

재배포 패키지를 찾아서 배포해 주셔도 되고, 디펜즈에 있는 DLL 파일들을 복사해서 같이 복사해 주셔도 됩니다. 편한 방법을 선택하시면 됩니다.


Dependency Walker 사용법

http://notgivuphil.tistory.com/413

[쥔장]--------------------------------
전에는 idasm (visual studio.net) 을 통해서 dll을 확인했었는데, dependency walker 라는 프로그램이 있다는 사실을 알고서 이에 대한 사용방법이 있기에 스크랩을 해본다.

하지만 봐도 잘 모르겠다는... ^^;
--------------------------------------

0 - Dependency Walker?

쉽게 이야기해서 프로그래밍이 사용한 DLL 정보와 DLL에 들어있는 함수 중 사용한 함수를 보여주는 툴 (~)

1- 프로그램위치 (VS 2005기준) – 편하게 아래쪽 그림 참고

2- 그럼 실행해보자 ^0^

(1) 연결된 DLL정보를 볼 프로그래밍을 선택하기 위해 아래 아이콘을 클릭한다.

(2) 연결된 DLL 정보를 볼 프로그래밍을 선택한다

< 참고로 난 안사람은 안다는 저 흐뭇한 게임의 속을 보려고 한다 *_ *(개인적취향에 존중을)>

! 프로그래밍을 선택하고 열기를 누르자!

(3) 나온 화면

잠시 아래 Warning은 무시하자.. 그냥 대충 보니 뭔가 미확인 DLL때문에 빠진 함수가 있다는 말인 것 같다.. 참고로 난 영어 못한다. 그래서 틀린 해석일 수도 있다는 점 밝힌다. ㅡㅡㅋ;

(4) 자 사용된 DLL과 그 DLL에서 사용된 함수를 봐보자!

딱 보니 이 흐뭇한 게임에 사용된 DX9 버전은 9_32 버전이라는 점과 함께 D3DXCreateEffect 사용된것 봐서 쉐이더 HLSL를 사용했다는 것이 보이군요 후후후

(5) 자 그럼 내 프로그래밍에서 사용된 DLL는 어디에?

파란색 네모에 있는 아이콘을 누르면 바로 DLL 있는 FullPaths 가 표시 된다.

(6) 기타

* 이외에도 여러 기능들이 있는 것 같으니 직접 한번 해보시길

* Dependency Walker에 아쉬운점은 바로 아까 무시한 워닝을 출력하게 한 것처럼

MS나 공식적인 DLL가 아닌 사용자가 만든 DLL (ex, 게임엔진의 DLL)는 표씨 하지 않는다는 점이다. (어떻게 생각해보면 당연한 것 일수도 있다.) -> 응? 아닌데 나오던데?

(7) 끝으로 프로그램을 배포할 때 무슨 DLL이 사용되었고 어떤 DLL를 포함해야 할지 이 프로그램으로 먼저 파악하고

아래 같은 상황이 생겨 당황해 하지 않기 바란다..

반응형
반응형

쓰레드와 프로세스 개발 일지

2010/10/25 10:45

복사 http://blog.naver.com/scmoon119/120117290967







쓰레드와 프로세스의 차이점을 묻는 질문은 개발자를 채용할 때 항상 물어 왔던 질문이다.

내 스스로 나에게 질문하여 보니 정작 구체적인 답이 떠오르지 않았다.

프로그램을 개발할 때 만들어 지는 프로그램이 구동되는 게 프로세스 아닌가?

프로그램 개발할 때 createThread 해서 동시에 여러개의 업무가 진행되게 하는 multi thread 프로그램을 많이 작성하였는데,

그렇다면 프로세스는 쓰레드를 여럿 가지고 있는 것 아닌가 정도의 상식적인 생각만 머리에 떠오른다..

기술은 상식이 아니다.

관련 내용을 정리해 보다.

쓰레드, 프로세스의

공통점

- 특정 순서로 실행해야 할 명령 시퀀스를 나타낸다.

- 비동기적 행위 (Asynchronous Activity)

차이점.

프로세스

- 운영체제 내에서 존재

- 레지스터 , 스택, 포인터, 실행중인 프로그램. 데이타의 복합체로 표현

- 각각 별개의 메모리 공간을 가진다.

- 실행중인 프로그램.

- 운영체제 내에 PCB (Process Control Block ) 존재

- 프로세서가 할당하는 개체

- 디스 패치가 가능한 대상

- 두개의 프로세스가 같은 프로그램을 사용시 별개의 프로세스로 인식한다. ( 코드부분은 같지만 각기 별도의 스택에 다른 자료를 가지기 때문이다. )

- 실행, 대기 또는 보류, 준비 의 status 를 가짐.

- 프로세스간 전환 속도가 쓰레드 간보다 느리다.

쓰레드

- 프로세스 내에서 존재

- 하나의 프로그램 내에서의 실행 단위

- 쓰레드가 메모리를 공유해서 사용할 수 있다.

- 완전한 병령처리는 아니다. 때로는 쓰레드를 동기화하여야 한다. 즉 쓰레드가 다른 쓰레드의 일을 기다리거나, 한쓰레드가 특정 리소스를 독점적으로 사용할 수 있는 기능이 필요한 경우가 많이 있어 개발이 복잡해 진다.

- 쓰레드간 전환 속도가 프로세스 간보다 빠르다.

- 멀티 쓰레드의 장점은 CPU가 여러 개일 경우에 각각의 CPU가 스레드 하나씩을 담당하는 방법으로 속도를 높일 수 있다.

- 멀티 스레드의 단점은 각각의 스레드 중 어떤 것이 먼저 실행될지 그 순서를 알 수 없다.

- 지원하는 주체에 따라 사용자 쓰레드와 커널 쓰레드로 나눌 수 있다.

- 멀티쓰레드를 이용하여 애플리케이션을 작성하는 데는 아래의 3가지 방법이 있다.

boss/worker 모델

work crew 모델

파이프 라이닝 모델

참고 자료.

http://luckydevil.tistory.com/394

http://msdn.microsoft.com/ko-kr/library/ms164740(VS.80).aspx

http://en.wikipedia.org/wiki/Process_(computing)

http://en.wikipedia.org/wiki/Thread_(computing)

http://fattarzan.tistory.com/attachment/dk130000000000.pdf

http://ko.wikipedia.org/wiki/%EC%8A%A4%EB%A0%88%EB%93%9C

http://blog.naver.com/onnon0225?Redirect=Log&logNo=60053807626

http://s1navro.egloos.com/1522204

http://xyzlast.springnote.com/pages/83273


반응형

+ Recent posts