얼마전 새로운 운영체제인 Windows 7 에서 C++ Builder 2009 사용시 발생하는 문제에 대하여 글을 쓴 적이 있는데 오늘 RSS Reader 를 탐독하다 해결책에 대한 글을 발견했다.
2009/04/17 - [Dev Story/Mess] - C++ Builder 2009 Bug on Windows 7
이 방법은 DLL 파일 중
조건부 점프(JZ : 0x74)를 무조건 점프(JMP : 0xEB)로 바꾸는 것이다.
1) bordbk***.dll 을 찾는다 ( Delphi 2007 의 경우 bordbk105.dll, Delphi
2009 의 경우 bordbk120n.dll 이다)
2) 원본 파일을 백업해 두고 dll
파일을 Hex Editor로 연다.
3) 다음 코드를 찾는다 (01 00 48
74 47 80 3D) 이 코드는 한번만 존재 한다.
4) 찾은
코드 중 74 를 EB 로 바꾸고 저장한다.
참고로 이
방법은 공식적인 방법이 아니란다.
자료 출처 :
http://www.delphifeeds.com/go/f/58293
http://www.delphifeeds.com/go/f/58308
C++ 프로그래밍에서 헤더의 중복 #include 를 방지하는 방법으로 #pragma once 와 #ifndef 를 활용하는 방법이 있다. 이 두 방법은 모든 컴파일러에서 동작하는 것은 아니다.
우선 사용법을 보면 #pragma once 의 경우 헤더의 상단에 한번 적용 하면 된다.
그리고 #ifndef 를 활용하는 방법은 아래 처럼 define 이 되지 않았을 경우 지정된 값을 지정하여 이후에 다시 불러 들이는 것을 방지한다.
위 두 가지 방법은 여러가지 면에서 차이가 있다.
우선 첫 번째의 경우인 #pragma once 의 경우 컴파일러 지시자로 이를 한번 인식한 후 다음부터 같은 파일의 경우 파일을 읽기조차 하지 않는다. 그래서 컴파일 단계의 파일 해석 단계는 두 번째 방법보다 빠르다. 하지만 컴파일러 지시자로 특정 컴파일러에서만 동작을 한다. 이 지시자는 Visual C++ 5.0 이상에서만 동작을 한다.
두 번째의 경우 모든 컴파일러에서 동작을 하지만 헤더 파일을 여러번 include 를 할 경우 매번 헤더 파일을 열어서 define 여부를 확인해야 하기 때문에 컴파일 과정인 파일 해석 단계에서 첫 번째 방법보다 다소 느리다.
두 가지 방법은 속도와 호환성 문제가 얽혀 있는데 무지 큰 프로젝트가 아닐 경우 속도에서는 크게 차이가 나지 않을 것 같고 Visual C++ 에서만 작업하는 것이 아니라면 호환성을 고려하여 두번째 방법을 사용하는 것이 좋아 보인다.
우선 사용법을 보면 #pragma once 의 경우 헤더의 상단에 한번 적용 하면 된다.
그리고 #ifndef 를 활용하는 방법은 아래 처럼 define 이 되지 않았을 경우 지정된 값을 지정하여 이후에 다시 불러 들이는 것을 방지한다.
위 두 가지 방법은 여러가지 면에서 차이가 있다.
우선 첫 번째의 경우인 #pragma once 의 경우 컴파일러 지시자로 이를 한번 인식한 후 다음부터 같은 파일의 경우 파일을 읽기조차 하지 않는다. 그래서 컴파일 단계의 파일 해석 단계는 두 번째 방법보다 빠르다. 하지만 컴파일러 지시자로 특정 컴파일러에서만 동작을 한다. 이 지시자는 Visual C++ 5.0 이상에서만 동작을 한다.
두 번째의 경우 모든 컴파일러에서 동작을 하지만 헤더 파일을 여러번 include 를 할 경우 매번 헤더 파일을 열어서 define 여부를 확인해야 하기 때문에 컴파일 과정인 파일 해석 단계에서 첫 번째 방법보다 다소 느리다.
두 가지 방법은 속도와 호환성 문제가 얽혀 있는데 무지 큰 프로젝트가 아닐 경우 속도에서는 크게 차이가 나지 않을 것 같고 Visual C++ 에서만 작업하는 것이 아니라면 호환성을 고려하여 두번째 방법을 사용하는 것이 좋아 보인다.
무심코 사용하는 구조체에 포함 된 함수로 메모리를 객체 수 만큼 차지
하는게 아닐까 하는 의심이 들어 테스트 해 보았다.
같은 멤버 변수를 갖는 구조체 두개를 선언하고 둘 중 하나에는 함수를 몇 개 추가하고 객체를 만들었을때 생성되는 메모리 위치를 비교해 보았다. 의심과는 다르게 메모리에 생성되는 구조체 객체는 함수에 대한 메모리 차지는 없었다.
virtual 함수의 경우 조금 다르다 하는데 그 부분은 좀 더 공부를 해 봐야겠다. (역시 기본이 중요한 것 같다.)
이 문제에 대한 Borland Forum 의 Lyn님의 답변
같은 멤버 변수를 갖는 구조체 두개를 선언하고 둘 중 하나에는 함수를 몇 개 추가하고 객체를 만들었을때 생성되는 메모리 위치를 비교해 보았다. 의심과는 다르게 메모리에 생성되는 구조체 객체는 함수에 대한 메모리 차지는 없었다.
virtual 함수의 경우 조금 다르다 하는데 그 부분은 좀 더 공부를 해 봐야겠다. (역시 기본이 중요한 것 같다.)
이 문제에 대한 Borland Forum 의 Lyn님의 답변
문자열이 Float 형 데이터가 맞는지 확인을 해야 했다.
가장 간단하고 확실한 방법은 정규식(Regular Expression)을 사용하면 될 것 같은데 문제는 MFC에서 정규식 라이브러리를 찾을 수 없다는 것이다. boost 라이브러리를 이용할 수도 있지만 현재 프로젝트에 추가 계획이 없어 검증하는 루틴을 만들어 보았다.
지수형 데이터 검증할 수 있어야 하지만 우선 단순 Float 형을 기준으로 검증 루틴을 만을어 보았다.
유효한 Float 형 문자열이 부호로 시작할 수 있으며 단 하나의 소수점만 갖고 있을 수 있다는 조건하에 구현하였다.
지수형(-123.45e-3)을 포함한 검증 루틴은 나중에 한번 만들어 보아야 겠다.
가장 간단하고 확실한 방법은 정규식(Regular Expression)을 사용하면 될 것 같은데 문제는 MFC에서 정규식 라이브러리를 찾을 수 없다는 것이다. boost 라이브러리를 이용할 수도 있지만 현재 프로젝트에 추가 계획이 없어 검증하는 루틴을 만들어 보았다.
지수형 데이터 검증할 수 있어야 하지만 우선 단순 Float 형을 기준으로 검증 루틴을 만을어 보았다.
유효한 Float 형 문자열이 부호로 시작할 수 있으며 단 하나의 소수점만 갖고 있을 수 있다는 조건하에 구현하였다.
지수형(-123.45e-3)을 포함한 검증 루틴은 나중에 한번 만들어 보아야 겠다.
SQLite 홈페이지를 방문하면 동적 라이브러리(DLL) 파일(sqlite3.dll)을 쉽게 다운로드 받을 수 있다.
정적 라이브러리를 만들때나 직접 컴파일을 하였는데 64비트용 프로그램 개발에 필요하여 64비트
환경에서 만들어진 dll이 필요하여 컴파일 방법을 찾아 보았는데 정보가 많지 않았다.
어렵사리 찾아서 정리를 해 보았다.
준비물
sqlite-source-3_6_16.zip
sqlitedll-3_6_16.zip
C++ Compiler ( Visual C++ 2005 )
우선 Visual C++ 2005에서 Win32 프로젝트 생성하고 응용프로그램 설정을 아래와 같이 종류를 DLL로 설정하고 추가 옵션에 "빈 프로젝트"로 설정한다.
생성된 프로젝트 폴더에 sqlite 소스 파일(sqlite-source-3_6_16.zip)을 풀어 놓고 sqlitedll-3_6_16.zip 파일에서 sqlite3.def 파일을 프로젝트 폴더에 풀어 놓는다.
프로젝트에 sqlite 소스 파일을 추가한다. 그리고 tclsqlite.c 와 shell.c 파일을 프로젝트에서 제거한다.
프로젝트 속성 페이지의 링크 메뉴의 입력 메뉴에서 모듈 정의 파일 항목에 sqlite3.def 로 설정한다.
위의 설정만으로 빌드를 하면 아래와 같은 링크 에러를 만나게 된다.
1>fts3_tokenizer.obj : error LNK2005: _sqlite3_api이(가) fts3.obj에 이미 정의되어 있습니다.
1>rtree.obj : error LNK2005: _sqlite3_extension_init이(가) fts3.obj에 이미 정의되어 있습니다.
1>rtree.obj : error LNK2005: _sqlite3_api이(가) fts3.obj에 이미 정의되어 있습니다.
1>sqlite3.def : error LNK2001: sqlite3_column_database_name 외부 기호를 확인할 수 없습니다.
1>sqlite3.def : error LNK2001: sqlite3_column_database_name16 외부 기호를 확인할 수 없습니다.
1>sqlite3.def : error LNK2001: sqlite3_column_origin_name 외부 기호를 확인할 수 없습니다.
1>sqlite3.def : error LNK2001: sqlite3_column_origin_name16 외부 기호를 확인할 수 없습니다.
1>sqlite3.def : error LNK2001: sqlite3_column_table_name 외부 기호를 확인할 수 없습니다.
1>sqlite3.def : error LNK2001: sqlite3_column_table_name16 외부 기호를 확인할 수 없습니다.
1>sqlite3.def : error LNK2001: sqlite3_table_column_metadata 외부 기호를 확인할 수 없습니다.
1>D:\MyProject\VS\sqlite3\Debug\sqlite3.lib : fatal error LNK1120: 7개의 확인할 수 없는 외부 참조입니다.
위의 에러들을 없애기 위해 아래 내용을 전처리기 정의에 설정한다.
SQLITE_ENABLE_FTS3
SQLITE_ENABLE_RTREE
SQLITE_ENABLE_COLUMN_METADATA

마지막으로 sqlite3ext.h 내용 중 일부를 수정한다.
원본 : #define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api = 0;
수정 : #define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api;
최종 빌드한다.
위의 내용은 32비트에서 진행된 내용이다. 64비트용이라고 크게 다른건 아니고 구성 관리자에서 Win32 구성을 복사하여 x64구성을 만들고 전치리기 설정에서 WIN32를 WIN64로 바꾸면 된다.
실제 동작 여부는 아직 테스트 해보지 않았다.
어렵사리 찾아서 정리를 해 보았다.
준비물
sqlite-source-3_6_16.zip
sqlitedll-3_6_16.zip
C++ Compiler ( Visual C++ 2005 )
우선 Visual C++ 2005에서 Win32 프로젝트 생성하고 응용프로그램 설정을 아래와 같이 종류를 DLL로 설정하고 추가 옵션에 "빈 프로젝트"로 설정한다.
생성된 프로젝트 폴더에 sqlite 소스 파일(sqlite-source-3_6_16.zip)을 풀어 놓고 sqlitedll-3_6_16.zip 파일에서 sqlite3.def 파일을 프로젝트 폴더에 풀어 놓는다.
프로젝트에 sqlite 소스 파일을 추가한다. 그리고 tclsqlite.c 와 shell.c 파일을 프로젝트에서 제거한다.
프로젝트 속성 페이지의 링크 메뉴의 입력 메뉴에서 모듈 정의 파일 항목에 sqlite3.def 로 설정한다.
위의 설정만으로 빌드를 하면 아래와 같은 링크 에러를 만나게 된다.
1>fts3_tokenizer.obj : error LNK2005: _sqlite3_api이(가) fts3.obj에 이미 정의되어 있습니다.
1>rtree.obj : error LNK2005: _sqlite3_extension_init이(가) fts3.obj에 이미 정의되어 있습니다.
1>rtree.obj : error LNK2005: _sqlite3_api이(가) fts3.obj에 이미 정의되어 있습니다.
1>sqlite3.def : error LNK2001: sqlite3_column_database_name 외부 기호를 확인할 수 없습니다.
1>sqlite3.def : error LNK2001: sqlite3_column_database_name16 외부 기호를 확인할 수 없습니다.
1>sqlite3.def : error LNK2001: sqlite3_column_origin_name 외부 기호를 확인할 수 없습니다.
1>sqlite3.def : error LNK2001: sqlite3_column_origin_name16 외부 기호를 확인할 수 없습니다.
1>sqlite3.def : error LNK2001: sqlite3_column_table_name 외부 기호를 확인할 수 없습니다.
1>sqlite3.def : error LNK2001: sqlite3_column_table_name16 외부 기호를 확인할 수 없습니다.
1>sqlite3.def : error LNK2001: sqlite3_table_column_metadata 외부 기호를 확인할 수 없습니다.
1>D:\MyProject\VS\sqlite3\Debug\sqlite3.lib : fatal error LNK1120: 7개의 확인할 수 없는 외부 참조입니다.
위의 에러들을 없애기 위해 아래 내용을 전처리기 정의에 설정한다.
SQLITE_ENABLE_FTS3
SQLITE_ENABLE_RTREE
SQLITE_ENABLE_COLUMN_METADATA
마지막으로 sqlite3ext.h 내용 중 일부를 수정한다.
원본 : #define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api = 0;
수정 : #define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api;
최종 빌드한다.
위의 내용은 32비트에서 진행된 내용이다. 64비트용이라고 크게 다른건 아니고 구성 관리자에서 Win32 구성을 복사하여 x64구성을 만들고 전치리기 설정에서 WIN32를 WIN64로 바꾸면 된다.
실제 동작 여부는 아직 테스트 해보지 않았다.




