반응형


C++ 코드로 MySQL DB와 연동하여 일련의 작업을 하는 프로그램을 제작중에 있다.


테스트 하면 워낙에 해괴망측한 이유로 에러를 뿜어내며 프로그램이 죽어대지만 이번 오류는 좀 기록을 해놔야 다음에 까먹어도 찾아볼수 있을것 같아 기록해 둔다.


보통 String 타입으로 쿼리문을 작성하여 C++ 소스코드 안에 적용해놓고 그 String 문자열 대로 쿼리문을 적용하는게 가장 일반적이다.


오라클 과는 다르게 왠지 모르게 간편한 MySQL을 선호하는 편인데 작업 도중 아래와 같은 오류를 만나게 되었다.



Column: 'Column_Name' in where clause is ambiguous 


생전 처음 만나보는 에러라서 해결방법이 막막했는데 의외로 구글링 하네 쉽게 나왔다.


문제가 되던 컬럼이 어느 테이블의 컬럼이냐를 제대로 지정안해줬기 때문에 생겨난 아주 기초적인 실수였다...



예를 들어 id라는 컬럼이 있는데 이것이 Table A에도 존재하고 Table B에도 존재한다면


당연히 쿼리에는 A.id 라던가 B.id 라고 확실히 지정을 해줘야 한다.


그런데 나 같은 경우는 예를 들어 아래의 쿼리를 실행했다.




SELECT * FROM A,B WHERE id = 10




이렇게 되면 WHERE 뒤에 있는 id가 A에서 온 id인지 B에서 온 id 인지 정확히 알수가 없어 해당 에러를 내뿜게 되는 것이다.


정작 FROM 으로 A와 B 테이블 모두 불러와놓고 이런 기초적인 실수나 하다니....


요즘 일이 많고 야근하다보니 머리가 어떻게 된것 같다. 가끔은 머리 좀 쉬어가면서 해야겠다.

반응형

log4cxx.liblog4cxx.dll을 컴파일 해서 추출을 해냈으니 이제는 이것을 적용해서 실제 log4cxx를 쓸수 있도록 해야 한다.

 

 

간단하게 과정을 선요약하고 시작하자면

 

1. 프로젝트 생성

2. 프로젝트 속성 -> 구성 속성 -> C/C++ -> 추가포함디렉토리 : log4cxx 헤더파일 경로

3. 프로젝트 속성 -> 구성 속성 -> 링커 -> 일반 -> 추가라이브러리디렉터리 : log4cxx.lib 파일 경로

4. 프로젝트 속성 -> 구성 속성 -> 링커 -> 입력 -> 추가종속성 : log4cxx.lib 입력 후 추가

5. log4cxx.dll을 실행경로에 복사

6. log4cxx.properties 설정파일 작성 및 폴더 복사

가 있다.

 

 

 

 

1. Visual Studio 2012에서 새로운 빈 프로젝트(Win32 콘솔 응용 프로그램)를 생성한다.

 

2. 생성된 프로젝트에서 main으로 쓸 cpp 파일 하나 생성 한다.

 

3. 다음과 같은 코드를 방금 만든 cpp 파일에 복사 및 붙여넣기 한다(샘플 코드)


#include <windows.h>
#include <string>
#include <iostream>
using namespace std;

#pragma warning ( disable: 4231 ) 
#include <log4cxx/logger.h>
#include <log4cxx/basicconfigurator.h>
#include <log4cxx/propertyconfigurator.h>
#include <log4cxx/helpers/exception.h>

#pragma comment(lib, "log4cxx.lib")
using namespace log4cxx;
using namespace log4cxx::helpers;

int main(void)
{
	try
	{		
		while(1){
		string filePath = "log4cxx.conf";
		PropertyConfigurator::configure(File(filePath));

		LoggerPtr rootlog = Logger::getRootLogger();
		LoggerPtr log = Logger::getLogger("");

		LOG4CXX_FATAL(log, "fatal output...");
		LOG4CXX_ERROR(log, "error output...");
		LOG4CXX_WARN (log, "warn  output...");
		LOG4CXX_INFO (log, "info  output...");
		LOG4CXX_DEBUG(log, "debug output...");
		Sleep(1000);
		}
	}
	catch(const Exception& e) {
		cout << "[ERROR] configure()\n" << e.what() << endl;
	}

	return EXIT_SUCCESS;
}

 







 

4. 그냥 바로 붙여넣기를 하면 아래와 같이 온갖 오류가 발생할 것이다. 이것은 log4cxx의 헤더가 추가 되지 않아서 그런 것이다. 헤더를 추가해야 한다.


=> 헤더를 추가하는 방법은 다음과 같다.

 

Alt + F7 키를 누르면 속성 페이지에 들어오게 된다. 속성 창에서 C/C++ - 일반 추가포함 디렉토리에서 log4cxx의 헤더파일들이 존재하는 폴더 경로를 지정하면 된다.

 

대체로 apache-log4cxx-0.10.0/src/main/include/log4cxx에 존재하나 없을 경우

 

윈도우에서 logger.h를 검색해서 나오는 결과 파일의 경로를 찾아도 된다.

 

여기서 중요한 것은 /src/main/include/log4cxx까지 왔을 때 log4cxx 폴더를 경로로 잡는 것이 아니라 include 폴더를 경로로 잡아야 한다.

 

apache-log4cxx-0.10.0/src/main/include를 경로로 잡을 것.


<오류 투성이의 코드들... 헤더가 적용이 되지 않아 그렇다 >


<log4cxx 라는 폴더 안에 헤더파일이 몽땅 들어있다>

< 추가포함 디렉터리에 log4cxx 폴더 경로를 지정하면 오류들이 모두 사라진다.>


 

그러면 위와 같이 오류들이 모두 사라진다.

 

 








5.
이제 log4cxx 라이브러리 파일의 경로를 지정해줘야 한다.

 

나 같은 경우 생성한 프로젝트 폴더 안에 lib이라는 폴더를 임의로 만든 다음 log4cxx.lib의 파일을 옮겼다.

 

이렇게 하면 경로가 단순해지고 라이브러리 파일이 어디있는지 알아보기가 쉽다.

예를 들어 나는 Test라는 프로젝트를 만들어 지금 소스 코드를 입력했으니

 

Test 프로젝트 폴더 안에 만든 것이다.




위와 같이 라이브러리 파일을 집어 넣었다.(폴더명도 lib이라는 것이 보일것이다)

 

이제 이 라이브러리 파일이 있는 경로를 지정해주면 된다.

 

속성(Alt + F7) - 구성 속성 링커 일반 추가 라이브러리 디렉터리에서 경로를 지정해주면 된다.

 

 

 





6. 마지막으로 log4cxx.lib을 입력만 해주면 된다.

 

속성 구성 속성 링커 입력 추가 종속성에서 log4cxx.lib을 입력해서 확인

 

 

 


 

 

 

7. 이제 비주얼 스튜디오 내에서의 설정은 끝났고 컴파일해서 얻었던 log4cxx.dll을 옮겨야 한다. 그렇게 하기 위해선 우선 복붙해놓은 소스코드를 빌드 시켜 프로그램으로 만들어야 한다. Ctrl + Alt + B를 눌러 빌드 시킬 것.

 

그렇다면 프로젝트 폴더에 Debug라는 폴더가 생성되며 exe 파일이 생성되어 있다.

 

Debug 폴더에 컴파일해서 만들어 놓은 log4cxx.dll을 복사해둔다.

 







 

8. Test.execmd를 이용해 실행시킨다. cmd에서 Test.exe가 위치한 폴더로 이동시킨 다음 Test.exe를 입력하여 엔터를 친다.

 

 

 

 

그러면 이렇게 에러가 발생한다. 이 이유는 log4cxx.conf 파일 즉 설정파일이 없기 때문이다.


영어를 읽을줄 안다면 configuration file인 log4cxx.conf를 read 할수 없다라는 말이 고스란히 적혀 있다.

 

아까전 복붙했던 소스 코드를 잘 보면 filePathlog4cxx.conf로 되어있는데 이것은 컴퓨터공학을 전공했던 사람들이라면 누구나 알겠지만 log4cxx.conf 파일이 실행파일과 같은 위치에 있어야 한다는 것을 의미한다. 그러니 log4cxx.conf를 만들고 설정을 하면 된다.

 

 


9.
메모장에 아래와 같은 내용을 집어넣고 저장할 때 log4cxx.conf라고 저장한다음 아까전 실행파일이 위치했던 곳으로 복사시킨다.

 


# root logger setting
#log4j.rootLogger=DEBUG, console, filelog, chainsaw, rollingfile
log4j.rootLogger=console,FILE,rollingfile

# using console appender
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{ISO8601} [%-5p] %c(%L) : %m%n
#log4j.appender.console.layout.ConversionPattern=%d [%t] %-5p (%F:%L) - %m%n


# using rolling file appender
log4j.appender.rollingfile=org.apache.log4j.RollingFileAppender
log4j.appender.rollingfile.layout=org.apache.log4j.PatternLayout
log4j.appender.rollingfile.File=Rlog.txt
log4j.appender.rollingfile.layout.ConversionPattern=[%d] [%-5p] (%L) - %m%n
log4j.appender.rollingfile.MaxFileSize=500MB
log4j.appender.rollingfile.MaxBackupIndex=3

# using filelog appender
log4j.appender.FILE=org.apache.log4j.DailyRollingFileAppender
log4j.appender.FILE.DatePattern='Main-'yyyy-MM-dd-HH-mm'.log'
log4j.appender.FILE.Append=true
log4j.appender.FILE.ImmediateFlush=true
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.DateFormat=ISO8601
log4j.appender.FILE.layout.ConversionPattern=%d %-4r [%t] %-5p %c %x - %m%n

# using chainsaw appender
log4j.appender.chainsaw=org.apache.log4j.net.SocketAppender
log4j.appender.chainsaw.remoteHost=localhost
log4j.appender.chainsaw.port=4445
log4j.appender.chainsaw.locationInfo=true 

 


 

 

 

10. 이제 다시 cmd를 이용해 Test.exe를 실행시키면 실행도 제대로 되고 Main으로 시작하는 로그 파일도 생성이 된다. 로그 파일을 열어보면 프로그램이 실행하면서 출력했던 내용들이 고스란히 기록되어 있다.

 

 

 < 더이상 에러가 발생되지 않는다. 그리고 분 단위로 로그가 생성되는 것을 실시간으로 확인할수 있다>

 

 

<이렇게 로그가 생성되는 것을 확인 할수 있다. 프로그램이 꺼지지 않는한 이 로그는 계속 생성 될 것이다>

 

 

 

 

 

 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 


로그를 남기는 것은 상당히 중요한 일이다. 특히 현업에서 개발자로서 일을 한다면 더욱더 그렇다.


만약 어떠한 프로그램에 문제가 생겼을 경우 이 프로그램이 어디서 문제가 생겼는지 찾는 것은 대단히 어려운 일이다. 왜냐하면 대체로 개발하는 프로그램들은 테스트를 할때 기본적으로 며칠은 계속 구동을 시켜놓기 때문이다. 


이렇게 스트레스 테스트를 하여서 나오는 오류를 잡아야 하는데 사람이 며칠 동안 컴퓨터만 계속 쳐다볼수 없는 노릇이므로 로그를 남기게 해서 오류가 생겼을시에 언제, 몇시, 어느 부분에서 문제가 생겼는지 명확히 알수 있게 된다.

 

 또한 책임을 명확하게 할수도 있다. 혹여나 프로그램이 오류가 생겼는데 고객사와의 관계 혹은 특정한 경우에 의해서 그 잘못을 뒤집어 쓰는 경우가 생길수도 있는데 로그를 정확하게 남긴다면 이런 책임소재를 명확히 할수 있다. 특히 대단히 큰 프로젝트를 맡아 여러 회사와 같이 협업을 하는 경우가 있다면 더욱더 이런 책임소재를 명확히 할 필요가 있다.


로그를 남기는 버릇을 들여 어떠한 상황에서도 반드시 로그를 남기는 개발을 하여야 할것이며 그 일은 log4cxx가 C++ 환경의 개발에서 책임을 져줄것이다.



 







반응형

log4cxx는 프로그램의 로그를 기록해주는 역할을 하는 log4j의 개념과 원리를 따서 C++에도 적용할수 있게 한 오픈 프레임워크이다.


Apache에서 주관하였으나 2008년 이후로 최신버전은 나오고 있지 않다. 하지만 아직까지도 많이 쓰이는 대표적 C++ 로그 오픈 프레임워크인 만큼 필요성은 언제나 언급되고 있다.


하지만 log4cxx의 라이브러리를 얻기 위한 컴파일 과정 특히 윈도우 상에서의 컴파일 과정이 생각보다 까다로운 편이라 초보개발자 혹은 컴퓨터 전공 대학생들은 쉽게 따라하기가 어려운 케이스가 존재한다.


이 글을 작성하는 것은 서술식으로 전문용어가 주르륵 나열되어 있어 마치 지식 자랑을 뽐내는 듯한 블로그 포스팅을 지양하고, 최대한 사진을 포함하여  누구나 쉽게 컴파일을 할수 있도록 하는 것에 그 목적이 있다.



이 과정만 따라가면 누구나 컴파일을 할수 있을 것이다. 그 누구나의 최소 기준은 컴퓨터를 전공으로 할 계획이 있는 고등학생이다. 


일반인은 log4cxx와 같은 로그 오픈 프레임워크 자체를 만져볼 일이 거의 없을 것이기 때문이다.



- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


log4cxx를 윈도우에서 사용하기 위해서는 컴파일을 통해 log4cxx.liblog4cxx.dll을 생성해야 함. 컴파일 과정이 다음과 같음.



 

1. apache log4cxx 0.10.0 다운로드 http://logging.apache.org/log4cxx/latest_stable/download.html

-> Mirrosapache-log4cxx-0.10.0.zip 클릭후 다운로드

 



2. APRAPR-util을 다운로드 : http://apr.apache.org/download.cgi

-> apr-1.5.2-win32-src.zip 과 apr-util-1.5.4-win32-src.zip 클릭하여 다운로드





 


 

 


3. 각각 압축을 풀면 아래와 같은 결과물이 나오는데 apr-1.5.2 -> aprapr-util-1.5.4apr-util로 반드시 이름 변경 할 것








 

 



4. cmd에 들어가 apache-log4cxx-0.10.0 폴더로 들어간뒤 configure.batconfigure-aprutil.bat을 실행시킨다.

   cmd 내에서 폴더 이동 방법은 ‘cmd 명령어를 검색해 알아볼 것.


=> configure-aprutil.bat을 실행할 때 오류가 나는데 안나면 다행이고 오류가 나도 이상할건 없다무시해도 상관없다.






 

 


 



5. apache-log4cxx-0.10.0
폴더에 project 폴더가 존재한다. project 폴더로 들어간뒤 log4cxx.dsw를 더블클릭해서 솔루션을 실행시킨다 업그레이드도 실행 할 것.


<apache-log4cxx-0.10.0 폴더 내부>


<apache-log4cxx-0.10.0의 project 폴더 내부>


 


 

 

혹시나 log4cxx.dsw를 실행했을때 위와 같은 단방향 업그레이드 안내가 뜰경우에 확인하여 넘길 것.(취소하면 안된다)



 

 

6. log4cxx 프로젝트에 우클릭 한다음 시작프로젝트로 설정을 클릭한다.

 


 

 

7. 솔루션 탐색기에서 apu.hw 검색 후 소스 코드에서 #define APU_HAVE_APR_ICONV를 찾으면 1이라 되어있을건데 0으로 수정



<솔루션 탐색기에서 apu.hw 검색 결과>



<apu.hw 소스코드에 APU_HAVE_APR_ICONV를 1에서 0으로 바꿈>




8. 7번과 똑같은 과정으로 솔루션 탐색기에서 apr_ldap.hw에서 #define APR_HAS_LDAP 부분이 1로 되어있을 것인데 0으로 바꿔준다.

=> 과정은 7번과 완전히 똑같다. 


 

9. 빌드를 한다.(단축키 : Ctrl+Alt+B)



 


10. apache-log4cxx-0.10.0\projects\Debuf
폴더에 결과물을 확인한다.

=> log4cxx.dll과 log4cxx.lib 두개의 파일이 존재해야만 컴파일이 완전히 성공한 것이다.



 


 


 

* “error C2252: 템플릿은 네임스페이스 범위에서만 명시적으로 인스턴스화할 수 있습니다.” 오류가 발생할 경우 해결 방법

 

1) 솔루션 탐색기에 stringhelper.cpp 검색후 소스코드 들어가서 #include <iterator> 구문 추가

 

2) 솔루션 탐색기에 log4cxx.h 검색후 소스코드 들어가서

 

template class LOG4CXX_EXPORT std::allocator<T>;\

template class LOG4CXX_EXPORT std::vector<T>;\

 

extern template class LOG4CXX_EXPORT std::allocator<T>; \

extern template class LOG4CXX_EXPORT std::vector<T>; \

 

를 삭제한다.

 

*"error LNK2019: _imp_UuidCreate@4 외부 기호(참조 위치:_apr_os_uuid_get@4 함수)에서 확인하지 못했습니다." 오류가 발생할 경우 해결방법


=> Rpcrt4.lib을 링크에 추가


위 두개의 에러 발생시 자세한 처리 과정은 추후 다룰 예정.




+ Recent posts