본문 바로가기

김탱 개발자/윈도우프로그래밍

컴파일 옵션 (/MT /MD 등등)

opencv 라이브러리와 다른 라이브러리 2개를 같이 사용하는 DLL을 만들게 되었는데 DLL제작하는 프로젝트와 DLL 을 테스트하는 프로젝트에서 모두 "~정의가 이미 되었습니다" 라는 에러를 발생하였다.

찾아보았더니, 링크버전이 다를 경우 이런 에러가 발생하게 되었고 모든 프로젝트의 컴파일 옵션을 /MT로변경하였더니 잘 작동이 되었다.

DLL 을 만드는것이기 때문에 당연히 /MD로 컴파일을 하려고했으나 외부 라이브러리가 /MT 로 제작된것이라면 이런 에러가 발생한다. 따라서 하나로 통일하는것이 중요하다.

또한 굳이 /MD로 컴파일 안하더라도 DLL 제작에 문제는 없다.


추가적으로, 프로그램와 라이브러리가 런타입 옵션이 다른 경우에 정상적으로 빌드가 되는 경우가 있는데,

그냥 사용할 경우 사용 도중 프로그램이 뻗어버리는 문제가 발생 할 수 있다.

열심히 구글링 해본 결과, 결론은 하나, 런타임옵션은 메인 프로그램과 아래 라이브러리 모두 통일하자!

이유는, /MT 는 각 모듈별로 메모리를 할당/관리 하는 반면

/MD는 메모리관리를 공유하기 때문인데, 혼용해서 쓰게되면 다른 메모리쪽을 침범할 수 있기 때문이다.


//아래부터 퍼옴 글


/MT와 /MD 차이


컴파일 옵션중에 /MT(multi-threaded), /MD(multi-threaded dll)라는게 있습니다 (설정위치: 프로젝트속성-C/C++-코드생성-런타임라이브러리). 특히나, 정적 라이브러리를 사용할 경우에는 이것 때문에 무척 골치가 아픕니다. XXX is already defined in YYY 어쩌구 하는 라이브러리 충돌 컴파일 에러들은 모두 이놈들 때문에 발생합니다. 사용한 라이브러리가 하나는 /MT로 생성되었고 하나는 /MD로 생성되었다면 짤없이 라이브러리 충돌 에러 메시지를 보게 됩니다. http://msdn.microsoft.com/ko-kr/library/2kzt1wy3(v=vs.90).aspx에 보면 /MT, /MD가 설명되어 있지만 핵심 내용은컴파일시 정적 버전의 C 런타임 라이브러리를 사용할 것이냐(/MT) 아니면 동적 버전을 사용할 것이냐(/MD)의 차이입니다.


/MT: 응용 프로그램에서 다중 스레드 정적 버전의 런타임 라이브러리를 사용하도록 지정합니다. 즉 응용 프로그램에서 입출력, 메모리 할당과 같은 C 런타임 라이브러리(CRT, C Run-Time library) 기능을 사용할 때 정적 링크 버전인 LIBCMT.lib를 사용하여 프로그램이 빌드됨.


/MD: 응용 프로그램에서 다중 스레드 DLL 전용 버전의 런타임 라이브러리를 사용하도록 지정합니다.  즉 응용 프로그램에서 C 런타임 라이브러리 기능을 사용할 때 이것의 동적 링크 버전인 MSVCRT.lib를 사용하여 프로그램이 빌드됨.


만일 사용하는 외부 라이브러리는 /MT로 빌드되었는데, 현재 응용 프로그램은 /MD로 빌드하면 동일한 기능에 대해 서로 다른 두 버전의 라이브러리가 동시에 사용되기 때문에 XXX is already defined in YYY 어쩌구 하는 무수한 충돌 메시지를 보게 됩니다. 외부에서 가져온 라이브러리라면 /MD, /MT를 맞추거나 /NODEFAULTLIB:library 외에는 별 방법이 없지만(이렇게 해도 해결 안되는 경우가 많음), 자신이 직접 정적 라이브러리를 만들 경우에는 라이브러리든, 응용프로그램이든 모조건 다 /MT 옵션으로 맞추면 됩니다(debug용은 /MTd).


출처 : http://darkpgmr.tistory.com/50

///////////////////////////////////////////////////////


MFC DLL 종류 및 /MD, /MT 차이

DLL은 크게 세종류로 나누어집니다. 
[일반], [확장], [MFC 확장]
...
1. [일반] - 함수를 export하는 보통의 DLL 입니다. 
호환성을 위하여 주로 extern "C"를 사용합니다.

2. [확장] - 함수 뿐 아니라 C++ 클래스를 export하는 DLL 입니다.
여기서는 extern "C"를 사용할 수 없습니다.

3. [MFC 확장] - 확장 DLL을 기본으로 하면서 '공유 MFC Dll'을 
연결한 것으로 오직 /MD에서만 사용할 수 있습니다. 

[일반]과 [확장] DLL의 경우 _USRDLL이 선언되고,
[MFC 확장]의 경우 _AFXEXT가 선언됩니다. 
[일반]과 [확장]은 CRT 관련 기능을 DLL로 연결하거나 (/MD)
정적 라이브러리로 연결할 수 있습니다. (/MT)
그에 비해서 [MFC 확장] DLL은 오직 (/MD)만 가능합니다. 
[확장] DLL에서도 MFC를 사용할 수 있어서 
[MFC 확장] DLL과 무슨 차이가 있는지 궁금할 수 있는데요.
그 부분은 좀 더 알아보아야 할 것 같습니다. 
제가 테스트하기로는 [MFC 확장]을 사용하지 않아도 
[확장] DLL에서 MFC 클래스를 사용하는데 큰 문제가
있는 것은 아니었습니다.

윈도우 C++ 프로그래밍시 /MD, /MT 개념이 나와서 어려운 경우가
있습니다. 

간단히 정리해서 C++ 프로그래밍을 할 때 중요한 것을 꼽으라고 
한다면 바로 C Runtime Library(CRT)와 CPP Library(STL)라고...
할 수 있습니다. C++ 프로그래밍시 반드시 시스템 or 컴파일러에
의해서 기본적으로 제공되어야 합니다. 추가적으로 MFC도 
넣을 수 있습니다. 



즉, 윈도우 프로그래밍시 기본적으로 제공되어야 하는 것은
CRT, STL, MFC 라고 할 수 있습니다. 

/MD, /MT는 위의 세 라이브러리를 어떤 형식으로 연결시킬 것인지를
나타내는 것입니다.

DLL로 제공할 지, Static Library로 제공할지 여부입니다. 
만일 DLL로 제공할 경우 실행 이미지(exe)를 만들 경우 시스템 제공 dll을 사용하므로 크기가 커지지 않을 것이고, Static Library로 사용할 경우 실행 이미지에 관련 기능이 추가되므로 크기가 커질 것입니다. 

/MT (Static Library) 에서 다음 정적 라이브러리에 연결됩니다. 
CRT - libcmt.lib
STL - libcpmt.lib
MFC - nafxcw.lib 

/MD (DLL 연결) 에서는 다음 임포트 라이브러리에 연결됩니다. 
CRT - msvcrt.lib (즉, msvcr##.dll 에 연결)
STL - msvcprt.lib (즉, msvcp##.dll 에 연결)
MFC - mfc##.lib, mfcs##.lib (즉, mfc##.dll) - #‪#‎은‬ VS 버전

가끔 /MD, /MT 중 어느것이 좋으냐는 질문을 받곤 하는데요. 경우에 따라서 다릅니다만 저 같은 경우는 /MT를 선호합니다.  /MT를 선택할 경우 실행 바이너리가 커지는 단점이 있긴 
하지만 네트워크 환경이 좋은 상태에서 전송에 큰 부담이 없을 뿐 아니라, /MD를 선택할 경우 VS2008 이전 버전까지는  Manifest에 의해서 DLL Hell 문제가 발생하곤 했는데, /MT를 사용할 경우 완전 독립적이기 때문에 안정적이라는 장점이 있습니다.

출처 : http://devluna.blogspot.kr/2014/12/mfc-dll-md-mt.html


'김탱 개발자 > 윈도우프로그래밍' 카테고리의 다른 글

VB6.0 호환 DLL 제작  (0) 2016.02.22
CFile 클래스사용 csv파일로 저장 (유니코드)  (0) 2015.12.01
spreadsheet activex control  (0) 2015.11.30
DLL 제작  (0) 2015.11.30
GDI+ 사용법 (링크)  (0) 2014.07.11