블로그 이미지
대갈장군

calendar

1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30

Notice

Machine Learning에 대한 설명이 매우 잘 되어 있는 사이트.


http://openclassroom.stanford.edu/MainFolder/CoursePage.php?course=MachineLearning


다만 영어라는 점...

posted by 대갈장군
2013. 4. 13. 05:34 프로그래밍/MSDN

요즘 작업중인 프로젝트는 C++/CLI를 이용한 몇개의 프로젝트인데 중간 중간 C# 폼이 사용된다. 물론 Managed code와 Unmanaged code (Native code)를 함께 사용하기 위해서는 C++/CLI를 사용해야 한 다는 것 쯤은 나도 알고 있지만 왜 그럴까에 대한 진지한 생각은 해본적이 없다.


Stackoverflow 사이트를 돌아다니다 보니 좋은 글이라고 링크해 놓았길래 한번 번역해본다.


출처 - http://msdn.microsoft.com/en-us/magazine/dd315414.aspx


1. 언제 Managed-Native Interop이 사용되어야 하는가?

뭐 주절주절 써놓았는데 중간에 딱 한 문단이 마음에 확 와닿는다. 


These three applications address the three most common reasons to use interop: to allow managed extensibility of preexisting native applications, to allow most of an application to take advantage of the benefits of managed code while still writing the lowest-level pieces in native code, and to add a differentiated, next-generation user experience to an existing native application.


세가지 예시를 들면서 언제가 Managed 코드와 Native 코드를 섞어서 쓰는게 좋은가에 대해서 설명한 다음에 위와 같이 정의했다. 


"이러한 세가지 어플리케이션은 interop (Managed code와 Native code를 섞어쓰는 것을 말함)를 사용하는 가장 흔한 세가지 이유를 나타낸다: 원래 존재하던 native 어플리케이션에 managed 확장 가능성을 허락해 주는 것이 첫째이고, 둘째는 native 코드의 저레벨 코딩을 계속 쓰면서 동시에 managed code의 이점을 취할 수 있는 것이고, 마지막으로 셋째는 현존하는 native 어플리케이션에 차별화된, 또는 차세대 사용자 경험을 추가할 수 있기 때문이다."


영어를 한국어로 번역하다보면 적절한 한국어 찾기가 뜻을 이해하는 것보다 훨씬 더 어렵다. 젠장. 


2. Interop Technologies: 세가지 경우


There are three main interop technologies available in the .NET Framework, and which one you choose will be determined in part by the type of API you are using for interop and in part by your requirements and need to control the boundary. Platform Invoke, or P/Invoke, is primarily a managed-to-native interop technology that allows you to call C-style native APIs from managed code. COM interop is a technology that allows you either to consume native COM interfaces from managed code or export native COM interfaces from managed APIs. Finally there is C++/CLI (formerly known as managed C++), which allows you to create assemblies that contain a mix of managed and native C++ compiled code and is designed to serve as a bridge between managed and native code.


.NET 프레임워크에서는 세가지의 interop 기술들이 사용가능한데 다음과 같다.

첫째는 Platform Invoke 혹은 P/Invoke라고 불리는 기술인데 이것은 주로 managed code에서 C-style의 native APIs (C 함수들)를 불러다 쓰기 위한 용도다. 

둘째는 COM interop인데 이것은 native COM 인터페이스를 managed code로 부터 사용하거나 혹은 native COM 인터페이스를 managed APIs(함수들)로 부터 Export 하기 위해서 쓴다. 마지막으로 대망의 C++/CLI가 있는데 (과거에는 managed C++로 명명되었죠) 이것은 manged code와 native C++ code가 공존하는 형태로써 managed와 native 코드 간의 '다리'역활을 위한 용도로 디자인 되었다.


시간만 많으면 세가지 용도 모두에 대해서 쓰고 싶지만 일단 중요한게 C++/CLI이니까 그것만 자세히 살펴보겠다.


3. Interop Technologies: C++/CLI


C++/CLI is designed to be a bridge between the native and managed world, and it allows you to compile both managed and native C++ into the same assembly (even the same class) and make standard C++ calls between the two portions of the assembly. When you use C++/CLI, you choose which portion of the assembly you want to be managed and which you want to be native. The resulting assembly is a mix of MSIL (Microsoft intermediate language, found in all managed assemblies) and native assembly code. C++/CLI is a very powerful interop technology that gives you almost complete control over the interop boundary. The downside is that it forces you to take almost complete control over the boundary.
C++/CLI can be a good bridge if static-type checking is needed, if strict performance is a requirement, and if you need more predictable finalization. If P/Invoke or COM interop meets your needs, they are generally simpler to use, especially if your developers are not familiar with C++.
There are a few things to keep in mind when considering C++/CLI. The first thing to remember is that if you are planning to use C++/CLI to provide a faster version of COM interop, COM interop is slower than C++/CLI because it does a lot of work on your behalf. If you only loosely use COM in your application and don't require full fidelity COM interop, then this is a good trade-off.
If, however, you use a large portion of the COM spec, you'll likely find that once you add back the pieces of COM semantics you need into your C++/CLI solution, you'll have done a lot of work and will have performance no better than what is provided with COM interop. Several Microsoft teams have gone down this road only to realize this and move back to COM interop.
The second major consideration for using C++/CLI is to remember that this is only intended to be a bridge between the managed and native worlds and not intended to be a technology you use to write the bulk of your application. It is certainly possible to do so, but you'll find that developer productivity is much lower than in a pure C++ or pure C#/Visual Basic environment and that your application runs much slower to boot. So when you use C++/CLI, compile only the files you need with the /clr switch, and use a combination of pure managed or pure native assemblies to build the core functionality of your application.

C++/CLI는 원래 native와 managed 세계를 이어주는 브릿지 (다리) 역활 용으로 디자인 되었다. 그리고 이것은 managed 와 native C++ code 둘 다 동시에 하나의 공통 어셈블리 (심지어는 같은 클래스로) 컴파일 될 수 있게 해주었고 standard C++ 호출을 어셈블리의 두 영역간에 할 수 있게 해주었다. C++/CLI를 사용할때 당신은 어셈블리의 어떤 부분이 managed인지 혹은 native인지 결정할 수 있다. 이로써 결과물로 나오는 어셈블리는 MSIL (Microsoft intermediate language)와 native assembly 코드의 짬뽕이 된다. (MSIL은 managed code를 위해 사용되는 .NET Framework의 기반 언어 기술이다.) C++/CLI는 매우 강력한 interop 기술로써 당신에 거의 완벽에 가까운 interop 경계 컨트롤을 제공한다. (내 맘대로 왔다리 갔다리 할수 있다는 말). 문제는 모든 컨트롤을 제공하므로 일일이 내가 알아서 다 컨트롤 해야 한다.... 젠장 장점이 단점이네?ㅋㅋ


C++/CLI는 만약 어느 정도의 퍼포먼스가 요구되고 보다 예측 가능한 결과가 필요할 때, 그리고 static-type 체킹이 필요한 경우 좋은 다리 역활을 한다. 만약 P/Invoke나 COM interop이 내가 요구하는 것을 충족한다면 C++/CLI보다는 P/Invoke나 COM이 더 사용하기 쉽다. 특히 C++을 잘 모른다면... 더더욱.


C++/CLI을 사용할 때 명심해야 할게 몇가지 있다. 첫째는 C++/CLI가 COM interop보다는 빠르다는 점이다. (왜 같은 의미의 문장을 두번 이어서 썼는지 모르겠지만 암튼 C++/CLI가 COM보다 빠르다는 이야기) 왜냐면 COM은 사용자를 대신해서 많은 업무를 수행하기 때문이다. 만약 COM을 아주 약하게 사용한다면 (쬐끔만), 그러면 COM 쓰는 것도 괜찮다.


하지만 만약 COM의 많은 부분을 가져다 쓰게 되면 C++/CLI interop은 사실상 무용지물이 된다. 속도를 위해서 C++/CLI를 선택했으나 COM이 전체적인 퍼포먼스를 낮추기 때문에 애시당초 걍 COM interop으로 가는게 더 좋다는 말이네. 


C++/CLI를 사용할때 두번째 주의할 것은 이 interop은 다리 역활로 만들어진 것이지 프로그램을 그렇게 작성하시오라고 만든 것이 아니라는 점이다. 뭐 이건 당연한 이야기다. C++로 다 짤수 있는 프로그램을 굳이 C++/CLI로 짜서 다른 managed code랑 썪어 버릴 필요가 없다는 말이다. 이 점이 사실 뼈아프게 들리는 이유는 C++로 작성된 거대한 프로그램에서 몇가지 추가하고 싶은 기능이 있는데 그것이 C#과 같은 managed code로 작성하는 것이 내 입장에서는 더 편하게 느껴질때가 종종 있다. 이때 좀 갈등을 하는데 사실 그냥 좀 불편하더라도 Windows API를 이용하는 것이 C#을 이용하는 것보다 나은것 같다.


C#의 문제점은 폼안에 존재하는 각각의 컨트롤이 폼이 소유하고 있는 스레드를 제외하고는 스레드에 안전하지 않다는 점이다. 즉, C#은 설계 당시부터 다른 언어 (특히 C++)와의 섞어 쓰기에 대해 큰 고려를 안했던 것 같다. 물론 돌아가는 방법을 제공하기는 하지만 좀 완벽하지 못하다.


오늘은 여기까지만 쓰고 다음에 나머지 부분에 대해서 마무리하도록 해야겠다.

posted by 대갈장군

DWORD DoSomething() 

{

__try

{

// Do something

}


__finally

{

// Release Global Resource

if(!AbnormalTermination())

{

// __try went well 

// No problem

}

else

{

// Global or local unwinding happended due to error

// Global unwinding: Memory access violation

// Local unwinding: continue; break;

}

}

}

posted by 대갈장군
2013. 2. 9. 00:07 풉...

이틀 전인가? 정글의 법칙이 개뻥이라고 폭탄 선언한 박보영 소속사 대표의 발언 때문에 인터넷이 소란스러워 졌다.


소속사 대표을 글을 읽어보니, 참으로 아이러니 했다. 우선 정글의 법칙이 개뻥 프로그램이라고 했는데 그렇다면 왜 박보영은 그런 개뻥 프로그램에서 죽을 고생을 한거지? 


뭔가 모순이다. 연출이 전부라는 식으로 말했지만 실제로는 박보영이 리얼로 죽다 살아 왔다는 말인데... 이거 뭔가 심오한 모순이다.


내가 보기에는 소속사 대표가 화가난 이유는 박보영이 단지 고생을 했다는 점이 분명히 아닐 것이다. 아마도 여러가지 문제가 결합되서 나타난 것 같다.


출국전에 아마도 소속사에서는 박보영이 심히 걱정이 되었으리라 생각이 된다. 그래서 PD에게 신신당부 했을테고 구구절절 잔소리를 현지에 가서 늘어놓았을게 분명하다.


그러다가 박보영이 숙소로 돌아와서 울었다거나 아니면 뭔 사단이 터져서 소속사 대표가 자신의 분노 수치를 감당하지 못하고 페이스 북에 완전 자폭 글을 올려버린다...


소속사 대표와 SBS는 황급히 문제를 덮지만 이미 퍼져버린 불신의 씨앗은 수많은 네티즌들의 의혹과 배신감으로 인해 무럭 무럭 자라가고 있는 상태다.


인셉션에도 나오지만 모든 것을 바꾸는 것은 아주 작은 생각에서 나온다는 말이 있다. 박보영의 소속사 대표는 바로 레오나르도 디카프리오가 자신의 아내에게 심어버린 생각처럼 시청자들에게 정글을 법칙은 개뻥이다라는 아주 희박한 생각을 심어줌으로써 그것이 많은 사람들로 하여금 진실로 머리속에 뿌리박히게 하는 실수를 저질렀다.


사실, 무한도전도 그렇고 연출이 가미되지 않은 리얼 버라이어티는 없다. 그런 사실을 몰랐다면 배신감이 클지 모르겠으나 나는 사실 그닥 감흥이 없다.


내가 정글을 법칙을 보는 이유는 김병만이 뭐든지 척척해내는 모습이 대단하기 때문이다. 그는 정말 달인인 것 같다. :)


우리는 살면서 우리의 생각이 무조건 맞다고 믿고 남들까지 그 사실을 믿게 만들려는 경향이 강하다. 특히 한국은 더 그런것 같다. 중요한 것은 다른 것도 포용할 수 있는 넓은 수용성을 가지는 것이 아닌가 싶다. 


분명한 사실을 근거로 맞다 틀리다를 말하는 것은 올바른 비판이다. 하지만 웃긴 것은 '분명한 사실'이라는 것을 증명하는 것이 말처럼 쉽지 않다는 점이다. 고로 유연한 생각을 가져야 한다.



posted by 대갈장군
2013. 1. 24. 00:34 나의 이야기



범죄와의 전쟁라는 영화를 봤다.


스토리는 사실 그렇게 대단하지는 않았다. 흔한 한국형 조폭 영화 같았지만 등장 인물들의 연기력 때문에 영화 몰입도는 정말 대단했다.


사실 나는 주성치 영화같은 말되안되는 스토리에 주인공이 말도안되는 능력을 갖게 되는 터무니 없는 영화를 좋아한다. 영화를 보고나면 가볍게 일어날수 있기때문이다.


무엇을 보든 간에 집중해서 보는 편이라 영화가 무거우면 몇일을 그 영화에 대해 생각하느라 다른 일이 안될 정도이다.


이 영화를 무겁게 만드는 이유중에 하나는 단연 최민식의 연기력이다. 하정우나 다른 배우들도 연기력이 뛰어나지만 영화라는 설정을 가볍게 무시하는 최민식의 현실감 넘치는 연기는 내가 영화를 보는 건지 몰래 그 상황을 훔쳐보는 것인지 착각을 일으킬 정도이다.


하정우의 건달 포스는 영화가 최민식 단독 모노 드라마가 되는 것을 방지해주는 좋은 감초였다. 마지막에 하정우의 눈빛 연기는 정말 대단했다. 정말 깡패 아니었을까? ㅋㅋ


세상이 돌아가는 것은 결국 권력에 의한 것이라는 것을 잘 보여주는 영화였다. 시대의 흐름을 거스르면 아무리 대단한 깡패라 할지라도 결국 사냥용 개에 불과 하다는 것을 말이다.


한국 사회에 깊이 뿌리 박혀 있는 지연과 인맥에 의한 부패한 권력을 고스란히 드러내는 영화. 결코 뿌리 뽑힐 수 없는 한국 사회의 문제점을 까발린 영화. 보면서도 아... 라는 탄식이 간간히 나오는 영화.. 


제 점수는요, 별 5개. ㅋㅋㅋㅋ 




'나의 이야기' 카테고리의 다른 글

조용필 - 꿈  (0) 2013.05.20
영화 인셉션에 나오는 명대사  (2) 2011.03.09
진실 = 변하지 않는 마음  (0) 2010.02.23
Alaska  (0) 2010.02.18
기도  (2) 2010.02.03
posted by 대갈장군
2012. 12. 18. 03:51 프로그래밍/C++


int _tmain(int argc, _TCHAR* argv[])

{

       TCHAR * str = NULL;

       __try

       {

              str = (TCHAR *)malloc(20);

       }

       __finally

       {

              if(str != NULL)           

              {

                     free(str);

                     str = NULL;

              }

       }

       return 0;

}


예외 처리는 안전한 소프트 웨어를 만들기 위한 기본인데 몇가지 주의해야 한다.


우선 __try 내부로 들어온 다음 __finally 를 무조건 통과해서 나가는 것이 기본적인데, 주의해야할 점은 어떤 알 수 없는 오류로 인해 __try 내부의 메모리 할당이나 리소스 할당이 실패하는 경우, __finally 내부에서 무조건 메모리나 리소스를 해제 하려고 하면 '선언'은 되었지만 '초기화'가 되지 않은 포인터의 경우에는 "Run-Time Check Failure #3 - The variable 'str' is being used without being initialized." 라는 에러가 발생한다.


초기화 되지 않았으므로 알 수 없는 값을 가지고 있어서 그렇다. 이런 문제를 막으려면 애당초 포인터를 선언 할 때, NULL 값을 넣어주면 __finally 내부에서 if 로 NULL인지 아닌지를 체크하는 문법이 문제가 없이 잘 동작한다.


예외 처리를 잘 해야 하는 또 다른 이유는 하드웨어나 예상치 못한 문제로 프로그램이 이상 작동을 할 때 프로그래머의 잘못이 아님을 보여줄 수 있는 최후의 방패이기 때문이기도 하다.





posted by 대갈장군
2012. 12. 18. 03:08 프로그래밍/Windows API

나중에 Copy & Paste 신공을 위해서 코드를 적어둠...


DWORD err;                    // Error Code

TCHAR errMes[1024];      // Error Message Buffer


// Do something here that can fail


err = GetLastError();


FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, errMes, 1024, NULL);


wsprintf(str, "Error Code = %d, Message = %s", err, errMes);


MessageBox(hWnd, str, "ERROR", MB_OK");


posted by 대갈장군
2012. 12. 15. 04:59 프로그래밍/C++

http://msdn.microsoft.com/en-us/library/dd293575(v=vs.100).aspx


오, 생각보다 간단하게 어플리케이션 재배포 패키지를 만드는 방법이 있넹? 뭐 아주 완벽하지 않지만 간단하고 빠르게 설치파일을 생성해 낸다는 점에서 꽤 괜찮은듯.  


우선, 내가 만든 프로그램 이름이 MyMFCApplication.exe라고 치자. 그러면 우선적으로 만들어야 할 파일이 setup.bat 파일이다. 이 파일에 다음과 같은 문장을 때려 넣자.

@echo off
vcredist_x86.exe
mkdir "C:\Program Files\MyMFCApplication"
copy MyMFCApplication.exe "C:\Program Files\MyMFCApplication"


뭐 간단히 예기하자면 도스 모드에서 실행될 명령어를 주욱 적어 놓은 것인데, 우선 vcredist_x86.exe파일을 실행하라는 말이고 이어서 "C:\Program Files\MyMFCApplication" 폴더를 생성하라는 말이고 다음으로는 내가 만든 어플리케이션을 복사해서 거기다 집어 넣으라는 말이다.


이게 왜 필요한지는 조금 있다 알게된다.


일단 cmd 윈도우를 열고 iexpress.exe를 치고 엔터! 그러면 아래와 같은 녀석이 나타난다.



Create new Self Extraction Directive File을 선택한 후 Next!


그 다음에는 Extract files and run an installation command 선택 후 Next!


그 다음에는 내 프로그램의 이름을 묻는데 내가 원하는 이름을 적어 놓고 Next!


그리고 Confirmation prompt 페이지에서는 No Prompt를 선택하고 Next!


다음으로 License agreement인데 Do not display a license를 선택 하고 Next!


이제 Packaged files 페이지에 도착했는데 여기서 이제 내가 만든 프로그램과, vcredist_x86.exe 파일과 아까 만들어 둔 setup.bat 파일을 넣어준다. 참, vcredist_x86.exe 파일은 Program Files 폴더 아래에 \Microsoft SDKs\Windows\v7.0A\Bootstrapper\Packages\vcredist_x86  에 가면 찾을 수 있다.



 

 위 그림에 보면 내가 만든 프로그램은 빠져 있는데 넣는걸 잊어 먹지 말자.. ㅋㅋ


그리고 다음을 눌러보면 Install Program to Launch 페이지에 도착하는데 거기서 Install Program 텍스트 박스에다가 다음과 같이 넣어준다.


cmd.exe /c "setup.bat"





뭐, 저 명령은 cmd (도스 윈도우) 띄워서 setup.bat 파일 실행하라는 말이다. 


그 다음으로 Show Window 페이지에서는 Default 선택 후 Next!


Finished message 페이지에서는 No message 선택 후 Next!


그 다음인 Package Name and Option Pages에서는 내가 원하는 Setup 파일 이름을 적되, 아래 옵션에서 Store files using Long File name inside Package 옵션을 반드시 켜고 둘째로 파일 이름의 끝에 Setup을 꼭 넣어줘라. (예를 들자면 MyMFCApplicationSetup.exe)





이제 거의 끝이 보인다... 그리고 Configure restart 페이지에서는 No restart 선택 후 Next! (설치후 재시작 할꺼냐는 말)


Save Self Extraction Directive 페이지에서는 Save Self Extraction Directive (SED) file 선택 후 Next!


그리고 최종적으로 Create package 페이지에서 Next 클릭!


이제 내가 iexpress.exe를 실행했던 폴더를 가보면 뭔가 이상한 파일이 하나 만들어져 있을 것이다. 





두둥. 이것이 인스톨 파일이다! 짜짠...


이걸 이제 내가 설치하고자 하는 컴퓨터에 복사해서 더블 클릭해보면 우선 vcredist_x86.exe가 실행되면서 해당 컴퓨터에 Visual C++ redistribution 패키지 (DLL파일들)를 자동 설치하게 된다.


그 다음에는 프로그램 폴더에 자동으로 폴더를 생성해서 내가 만든 어플리케이션을 거기다 복사해 준다. 필요한 파일들이 더 있다면 복사 명령을 더 setup.bat에 더 써넣고 패키지에 필요 파일들을 더 넣어주면 될것 이다.


왜 이런 방법이 있는지 몰랐지? ㅋㅋ 역시 MSDN은 길을 잃고 헤멜 필요가 있는 미로다. 




posted by 대갈장군
2012. 12. 15. 04:17 프로그래밍/C++

http://msdn.microsoft.com/en-us/library/8kche8ah(v=vs.100).aspx


이글은 Visual Studio 2010 C++을 겨냥한 것임을 미리 밝혀둔다.


알다시피 내 컴퓨터에서 작성한 프로그램이 다른 컴퓨터에서 잘 작동할 것이라는 핑크빛 꿈을 꾸는 경우가 많은데 현실은 정반대다. 그렇다면 내가 내 컴퓨터에서 작성한 코드가 다른 사람 컴퓨터에서 잘 돌아가게 하려면 무슨짓을 해야 할까? 정답은 DLL을 프로그램이랑 같이 포장해서 보내줘야 한다는 것인데, 어떤 DLL이 필요한지는 어떻게 알까? 


그중에 한 방법이 Dependency Walker를 이용해 내가 만들 어플리케이션의 필요 DLL들을 검색해보는 것이다.


사진을 첨부하려 했는데 첨부가 안되네~ 아무튼, Dependency Walker를 사용하면 해당 프로그램에 필요한 DLL 목록이 주루루룩 뜬다. 뭐 경고 중에는 가볍게 무시해도 괜찮은 것들도 많지만 Delay-load Dependency나 Explicit (Dynamic) Dependency가 아닌데 못찾겠다고 나오는 DLL들은 뭔가 문제가 있을 확률이 높으니 눈여겨 봐야 할 필요가 있다.

 

본인이 작성한 프로그램이라면 어떤 LIB 파일이 프로그램에 링크 되었는지 알고 있으므로 운영제체나 .NET 프레임워크에서 공통적으로 지원하는 공유 DLL을 제외하고 어떤 기타 DLL이 반드시 필요한지도 일반적으로는 알고 있어야 정상이다.

 

다음 표를 보면 어떤 DLL이 어떤 경우에 필요한지에 대해서 간단하게 설명하고 있다.

 

Visual C++ Library

Description

Applies to

atl100.dll

Active Template Library (ATL).

Applications that use ATL.

msvcr100.dll

C Runtime Library (CRT) for native code.

Applications that use the

 C Run-Time Libraries.

msvcp100.dll

Standard C++ Library for native code.

Applications that use the 

Standard C++ Library.

mfc100.dll

Microsoft Foundation Classes (MFC) Library.

Applications that use

 the MFC Library.

mfc100u.dll

MFC Library with Unicode support.

Applications that use the

 MFC Library and require 

Unicode support.

mfcmifc80.dll

MFC Managed Interfaces Library.

Applications that use the 

MFC Library with

 Windows Forms Controls.

mfcm100.dll

MFC Managed Library.

Applications that use the

 MFC Library with

 Windows Forms Controls.

mfcm100u.dll

MFC Managed Library with Unicode support.

Applications that use the

 MFC Library with 

Windows Forms Controls and

 require Unicode support.

 

그런데 마지막 문단에 보면 이런 말이 있다. 일반적으로 시스템이 제공하는 DLL들 예를 들자면 Kernel32.dll, User32.dll, Ole32.dll 같은 놈들은 원래 재배포가 필요가 없다. 왜냐면 윈도우즈를 쓰는 모든 컴퓨터에는 기본적으로 저놈들이 있게 마련이기 때문이다. 하.지.만! 문제는 윈도우가 여러 버젼이 있다는 점이다. 윈도우 7과 윈도우 7 서비스팩 1과는 많은 차이가 있다. 고로 이런 경우 같은 운영체제이다고 하더라도 프로그램이 안돌아 갈수 있다는 점! 고로, 반드시 업데이트를 통해서 업그레이드 하거나 아니면 마이크로소프트에서 제공하는 각종 리디스트리뷰션 패키지 (재배포 설치 파일들)를 통해서 필요한 부분을 설치해야 한다!

 

저거 생각보다 중요한 점이라는 점!










posted by 대갈장군
2012. 12. 14. 03:48 프로그래밍/Dependency Walker

정상적인 경우의 아이콘들


bullet

에러가 없는 정상적인 모듈들


bullet

Duplicate module. 이 모듈은 이미 어디선가 처리되어 임포트 되어 있는 모듈. 


bulletForwarded module. 다른 모듈을 호출하는 Forwarded module

bullet

Delay-load module. 런타임에 실질적으로 함수가 호출되면 로드 되는 '지연 로드 모듈'


bullet

Dynamic module. 다이나믹 모듈. 소스코드에서 LoadLibrary()를 통해 호출되는 경우를 말한다. 누가 호출했는지 모를경우에는 아마도 Profiling을 하면 찾을 수 있는듯.


bullet

다이나믹 모듈이긴 한데 LoadLibraryEx 함수를 이용하되 DONT_RESOLVE_DLL_REFERENCES플래그나 LOAD_LIBRARY_AS_DATAFILE 플래그가 셋 된 상태로 호출된 경우를 말한다. 


bullet

64-bit module. 64 운영 체제용 모듈이라는 말.



에러나 경고


bulletMissing module. 모듈이 없음. 검색 경로를 검사해 봤지만 모듈이 없는 경우. 

bullet

Invalid module. 유효하지 않은 모듈. 


bullet

Module warning. 경고! 이 모듈은 부모 모듈에서 요구하는 하나 혹은 그 이상의 호출 함수가 없는 경우이거나 또는 CPU 타입이 틀렸거나, 또는 로드 될때 초기화에 실패한 경우다. Parent Import Function List View를 이용하는 빠진 함수가 어떤 놈인지 확인 가능하다.


bullet

Delay-load module warning. 이 모듈은 부모 모듈에서 요구하는 한개 이상의 호출 함수가 없는 경우이거나 잘못된 CPU 타입인 경우이다. 마찬가지로 Parent Import Function List View를 이용하면 빠진 함수가 어떤 녀석인지 확인 가능하다. 


bulletDynamic module warning. 이 놈도 마찬가지인데 다만 이것은 그냥 경고에서 그칠 경우가 많다. 왜냐면 다이나믹하게 연결하기 때문에 실행중에는 문제없이 돌아갈 수 있다는 점. 

 

Dependency Walker는 수많은 에러와 경고 메세지를 출력해 내는데 몇몇은 아주 중요하고 나머지는 무시해도 되거나 문제가 되지 않는 놈들이다. 대부분의 에러 메세지는 두 개중에 하나다. Load-time failure 혹은 Run-time failure.


Load-time failure이라 함은 어플리케이션이 시작도 못해보고 실패한다는 말이다. 어플리케이션을 실행하기 위해 꼭 필요한 모듈들이 없거나 문제가 있어서 시작도 못했다는 것. 정확하게 말하자면 implict나 forward 의존을 하는 모듈들이 존재 하지 않거나 잘못되어 운영체제가 함수를 호출하는 entry point를 전혀 얻어내지 못한 경우다. 또 다른 형태의 load-time failure로는 윈도우가 기반이 아닌 모듈을 호출하거나 CPU 타입이 다른 모듈을 호출하거나 하는것이다. 


자, 몇몇 에러 메세지를 보자. 


bulletThe dynamic link library BAR.DLL could not be found in the specified path...

bulletThe procedure entry point FOO could not be located in the dynamic link library BAR.DLL.

bulletThe application or DLL BAR.DLL is not a valid Windows image.

bulletThe application failed to initialize properly.

bulletInitialization of the dynamic link library BAR.DLL failed. The process is terminating abnormally.

bulletThe image file BAR.EXE is valid, but is for a machine type other than the current machine.


대부분의 load-time 문제들은 Dependency Walker를 통해 즉각적으로 탐지 가능하다. Dependency Walker를 이용하면 implicit, forward 그리고 delay-load dependency를 바로 체크하여 문제가 있으면 알려준다. Implicit와 Forward 의존의 경우 실행이 아예 불가능하고 delay-load 의존의 경우에는 load-time에 필요하지는 않아서 일단 프로그램이 돌아가더라도 문제가 있는 모듈을 호출하는 순간 프로그램이 뽁 날 것이다. 


Run-time 의존적 모듈들은 프로그램이 실행된 후에 연결 (로딩) 된다. 일반적으로 이런 경우는 소스 코드 내에서 LoadLibrary 같은 함수를 호출함으로써 이루어진다. 일단 모듈이 로딩 된 후에는 어플리케이션이 GetProcAddress 함수를 이용해서 특정한 함수의 위치를 얻어낸다. 만약 어플리케이션이 아주 안전하게 작성이 되어서 실패를 핸들링 할 수 있다면 경고는 무시된다.


Run-time 의존을 사용하는 이유는 많이 있다. 우선 load-time 퍼포먼스가 증가한다. 즉, 실행하려고 더블클릭 하는 순간의 시간을 단축할 수 있다는 말. 왜냐면 필요할때 연결하면 되니까. 예를 들면 프린팅 하는 함수를 가진 모듈은 사용자가 정말로 프린트를 하고 싶을때 연결하면 된다. 그리고 또 다른 장점으로는 모듈이나 함수가 존재하지 않는 경우에 사용할 수 있다. 무슨말이냐 하면, 윈도우 NT 특유의 함수를 호출하고자 한다고 치자. 만약 이 모듈을 암묵적으로 포함하게 되면 이 어플리케이션이 윈도우 XP에서 실행되는 경우, 해당 모듈을 없으므로 에러가 터지고 실행이 안된다. 하지만 런타임으로 연결하면 일단 해당 컴퓨터에 필요로 하는 모듈이 있는지 없는지가 실행중에 파악이 된다. 고로 없으면 없는대로 다른 메세지나 처리를 통할수 있다. 암묵적으로 연결하면 아예 실행이 안된다.


런타임 의존은 두 가지 타입이 있다. 하나는 Explicit dependency (혹은 Dynamic dependency) 그리고 나머지 하나는 Delay-load dependency 이다. 명시적 의존은 (Explicit Dependency) 어플리케이션이 실행되는 도중에 아무때나 로딩될 수 있는 것이다. 그래서 어떤 명시적 의존이 어플리케이션에서 사용되는지 확인 하는 방법은 프로그램을 실행해보는 방법밖에 없다. (혹은 profiling) 명시적 의존은 어플리케이션이 LoadLibrary 함수와 GetProcAddress 함수를 코드 내에서 호출할 때 비로소 발생한다.


Delay-load 의존들은 사실 Explicit 의존처럼 구현되지만 헬퍼 라이브러리와 링커가 대부분의 일을 한다. 대부분의 윈도우 모듈들은 자신의 모듈안에 import table이라 불리는 호출 함수들의 리스트를 가지고 있다. 이 테이블은 링커에 의해서 작성되고 운영체제에 의해 사용되는데 주어진 모듈의 어떤 모듈들이 implicit인지 혹은 forward 의존인지를 알아내는데 사용된다. 이 리스트에 있는 모듈중에 찾을 수 없는 모듈은 당연히 어플리케이션의 실패를 초래한다. 만약 내가 링커에게 하나의 모듈을 delay-load 의존으로 연결하라고 지시하면, 그 모듈의 정보를 import table에 저장하는 대신, 그 모듈의 정보를 분리된 delay-load import table에 저장한다. 그리고 실행 시 (Run-time)에 만약 하나의 모듈이 delay-load 의존 모듈을 호출하게 되면 이 호출은 헬퍼 라이브러리에 의해 처리된다. 헬퍼 라이브러리는 LoadLibrary 함수를 이용해 모듈을 로드하고 GetProcAddress 함수를 이용해 해당 모듈로의 함수 진입점을 불러온다. 일단 이 과정이 끝나면 해당 함수를 호출한 모듈은 무슨일이 일어난건지 전혀 모르는 채 계속 하던일을 자연스럽게 하게 된다. 이러한 일련의 과정이 한바탕 치러지고 나서 나중에 호출되는 같은 함수나 혹은 같은 모듈 내의 다른 함수들은 헬퍼 라이브러리를 거치지 않고 바로 즉각적으로 해당 함수로 접근이 가능하다. 


Delay-load 헬퍼 라이브러리는 만약 실패가 있거나 오류가 있으면 유저에게 알려주는 메커니즘을 가지고 있다. Explicit 의존 (Dynamic 의존) 처럼 만약 어플리케이션이 이러한 오류나 실패에 이미 준비를 하고 있는 상황이라면 문제가 없다. 


요약하자면 ImplicitForward Dependencies 경우에는 반드시 모듈이 찾을 수 있는 위치에 존재해야 하며 또한 에러나 경고가 없어야 한다. ExplicitDelay-load Dependencies의 경우에는 모듈이 반드시 찾을 수 있는 위치에 있어야 하는 것도 아니고 또한 부모 모듈이 사용하고자하는 모든 함수를 다 Export 해야 하는 것도 아니다. 하지만, 만약 어플리케이션이 없는 Explict 모듈이나 Delay-load 모듈을 실행중에 사용하려고하면 이것은 Run-time Failure, 즉 실행중 프로그램 정지 (Crash)로 나타날 수 있다. Dependency Walker는 사용자가 소스 코드 내부에서 이러한 오류에 대한 방지책을 마련했는지 알 수 없으므로 모든 발생 가능한 오류에 대해 알려준다. 만약 어플리케이션이 아무 문제없이 잘 돌아가면 대부분의 경고 메시지는 무시해도 된다. 하지만 만약 어플리케이션이 실패하는 경우, 경고는 아마도 무엇이 실패를 가져오게 했는지에 대한 고찰을 하게 도와 줄 수 있을 것이다.


오호, Dependency Walker는 First and Second chance Exception에 대해서도 경고를 해준단다. 엑세스 바이얼레이션 (잘못된 메모리 참조) 같은 오류가 어플리케이션에서 발생하면 어플리케이션은 해당 예외를 처리할 한번의 기회를 얻는다. 이것을 흔히 First Chance Exception이라 한다. 만약 어플리케이션이 그 예외를 잘 처리하고 문제가 없으면 오케이지만 만약 어플리케이션이 이 예외를 처리하지 못하면 이것이 Second Chance Exception이 된다. 이 경우에는 주로 어플리케이션이 완전히 뽀싸진다. 크래쉬! 일반적으로 Second Chance Exception이 발생하면 운영체제는 사용자에게 다이얼로그 박스를 열어서 '야, 프로그램 엉망이라서 닫는다!'라고 알려주고 종료해야 한다고 말한다. 나에게는 종종 있는 일이다 ㅋㅋㅋ


Dependency Walker는 항상 이 Second Chance Exception을 기록한다. 물론 First Chance Exception도 기록할 수 있다. 많은 어플리케이션이 First Chance Exception을 일으키도록 작동하고 또 처리하고 한다. 고로 이것은 '완전 나쁜' 징후로 보지는 않는다. 









posted by 대갈장군