레이블이 C/CPP인 게시물을 표시합니다. 모든 게시물 표시
레이블이 C/CPP인 게시물을 표시합니다. 모든 게시물 표시

vscode clang-format style

# vscode c++ 포맷 스타일은 기본적으로 clang-format 을 사용한다.
# 포맷 스타일은 변경 예시
// linux 에선 clang 설치해야 다음을 사용할 수 있다.
"C_Cpp.clang_format_path": "/usr/local/bin/clang-format",
// .clang-format 파일이 있다면 이 설정에 따른 포맷팅
"C_Cpp.clang_format_style": "file",
// clang-format --style="google" aaa.cpp 로 사용
// .clang-format 파일이 없다면 사용할 포맷 스타일 디폴트 "Visual Studio"
"C_Cpp.clang_format_fallbackStyle": "visual studio",
// "C_Cpp.clang_format_fallbackStyle": "google",
// "C_Cpp.clang_format_fallbackStyle": "webkit",
// "C_Cpp.clang_format_fallbackStyle": "mozilla",

# 포맷 스타일 결과 비교, main 함수만 발췌
# 개인적으로 visualstudio 또는 google 스타일이 좋은것 같다.

# Visual Studio 는 Clang-format 기본스타일 종류에는 없고 다음과 같이 설정해야한다.
# clang-format --style="{UseTab: Never,IndentWidth: 4,
BreakBeforeBraces: Allman,
AllowShortIfStatementsOnASingleLine: false,
IndentCaseLabels: false,
ColumnLimit: 0}" hello_world.cpp
# 참고로 -i 옵션을 주면 변경된 스타일이 파일에 적용된다.
# 들여쓰기 탭, 시작 중괄호 한줄 차지
int main()
{
    string a = "1";
    if (a == "1")
    {
        cout << "hello world" << endl;
    }
    return 0;
}

# clang-format --style="google" hello_world.cpp
# 들여쓰기 공백2, 시작 중괄호 같은 라인에 시작
int main() {
  string a = "1";
  if (a == "1") {
    cout << "hello world" << endl;
  }
  return 0;
}

# clang-format --style="webkit" hello_world.cpp
# 들여쓰기 공백4, 함수 시작 중괄호만 한줄, 함수내에서는 같은 라인에 시작
int main()
{
    string a = "1";
    if (a == "1") {
        cout << "hello world" << endl;
    }
    return 0;
}

# clang-format --style="mozilla" hello_world.cpp
# 들여쓰기 공백2, 함수 시작 중괄호만 한줄, 함수내에서는 같은 라인에 시작
# 함수 리턴 타임 한줄 차지
int
main()
{
  string a = "1";
  if (a == "1") {
    cout << "hello world" << endl;
  }
  return 0;
}

g++ warning missing initializer for member

다음과 같이 time struct(tm) 생성시 초기화를 하지 않은 상태의 c++코드가 있을때

#include <iostream>
#include <sys/time.h>
int main() {
    struct tm aaa{};
    std::cout << aaa.tm_sec << std::endl;
    return 0;
}

다음과 같이 빌드 하면 괜찮은데,
g++ -std=c++11 ysoftman.cpp
또는
g++ -std=c++11 -Wall ysoftman.cpp

다음과 같이 -Wextra 옵션을 주면�warning 이 발생한다.
g++ -std=c++11 -Wextra ysoftman.cpp

ysoftman.cpp:5:16: warning: missing initializer for member ‘tm::tm_sec’ [-Wmissing-field-initializers]
  struct tm aaa{};
                ^
ysoftman.cpp:5:16: warning: missing initializer for member ‘tm::tm_min’ [-Wmissing-field-initializers]
ysoftman.cpp:5:16: warning: missing initializer for member ‘tm::tm_hour’ [-Wmissing-field-initializers]
...


참고로 -Wextra 는 -Wall 에 포함되지 않는 warning 에 대한것으로
위와 같이 초기화 누락이나 포인터를 정수형과 비교할때 발생하는 경고(comparison between pointer and integer) 를 활성화 한다.
그리고 -W 옵션 대신 -Wextra 를 사용하라고 한다.
g++ -v --help | grep Wextra
-W switch is deprecated; use -Wextra instead


[해결방법1]
-Wextra 를 사용하지 않기
찾아보니 사실 기본 0값으로 초기화되는데 gcc 는 너무 과도하게 warning 을 발생한다는 의견도 있다.

[해결방법2]
다음과 같이 모든 멤버를 초기화한다. (struct 내의 생성자()를 두고 초기화하면 편한데, tm 은 standard library라 그럴 수 없다.)
    struct tm aaa{
    .tm_sec=0,
    .tm_min=0,
    .tm_hour=0,
    .tm_mday=0,
    .tm_mon=0,
    .tm_year=0,
    .tm_wday=0,
    .tm_yday=0,
    .tm_isdst=0,
    .tm_gmtoff=0,
    .tm_zone=NULL};

[해결방법3]
경고 메시지대로 -Wno-missing-field-initializers 를 추가해서 초기화 경고만 제외시킨다.
g++ -std=c++11 -Wextra -Wno-missing-field-initializers ysoftman.cpp

도커 컨테이너에서 make -j 옵션

# 6cores(12threads), 32GB RAM 맥북에서
# 도커 컨테이너를 띄우고 c++ make 속도를 높이기 위해
# make -j 4 -> make -j 8 로 같이 병렬 컴파일 잡 개수를 높였다.
# 그런데 다음과 같은 에러가 발생한다.
g++: internal compiler error: Killed (program cc1plus)
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://bugzilla.redhat.com/bugzilla> for instructions.
make[1]: *** [util/utf8_string_bounder.o] Error 4
make[1]: *** Waiting for unfinished jobs....

# 위와 같은 에러는 빌드시 메모리 부족으로 스왑 파일을 사용하는데
# 스왑파일도 1GB 로 적어 컴파일을 끝낼 수 없어 발생한 에러다.
# 컨테이너의 메모리가 2GB 로 설정되어 있었다.
# 컨테이너에서 사용할 cpu, memory 를 늘려야 한다.(스왑파일도 늘리 수 있다.)
# 도커 setting -> resources -> advanced 에서 변경한다.


# 이제 컨테이너를 run 하고
docker run --name ysoftman_centos -dit ysoftman/centos

# 컨테이너에 접속해서
docker exec -u root -e COLUMNS=$(tput cols) -e LINES=$(tput lines) -it ysoftman_centos /bin/bash

# cpu, memroy 를 확인해 보면
# cpu 6, memory 8G 로 설정된것을 볼 수 있다.
cat /proc/cpuinfo  | \grep processor
processor : 0
processor : 1
processor : 2
processor : 3
processor : 4
processor : 5

free -h
              total        used        free      shared  buff/cache   available
Mem:           7.8G        326M        7.1G        868K        384M        7.2G
Swap:          1.0G          0B        1.0G

# 이제 make -j 8 을 수행하면 잘 된다.
time make -j8

# 컨테이너 리소스 증가에 따라 make 빌드 소요 시간도 줄지만
# 같은 리소스상태에서는 -j 값이 어느정도 부터는 시간이 더 이상 줄지 않는다.
# 2CPUs, 2GB mem, make -j 8 --> (2:12초)
# 6CPUs, 8GB mem, make -j 8 --> (1:42초)
# 10CPUs, 16GB mem, make -j 10 --> (1:39초)
# 10CPUs, 16GB mem, make -j 12 --> (1:39초)

# 참고
# make -j 옵션 사용시 값을 명시하지 않으면 무한대로 설정된다.
make --help | \grep  '\-j'
  -j [N], --jobs[=N]          Allow N jobs at once; infinite jobs with no arg.

# 무한대로 하면 모든 cpp 파일이 동시 컴파일 되고 더 많은 메모리를 필요로 해서
# 에러가 또 발생할 수 있어 memory 리소스에 따른 적절한 -j 수치를 정해야 한다.

vscode c++ template 연속 angle bracket 에러

# c++ 사용중 다음과 같이 중첩 template 사용시 >(angle bracket)이 연속으로 붙어 있는 경우
vector<vector<int>>

# mac에서 vscode problems 창에 다음과 같은 에러메시지가 나오고 있다.
a space is required between consecutive right angle brackets (use '> >')

# template 연속 angle bracket 에러는 c++11 에서 수정돼 컴파일시 문제가 없다.
# vscode 설정에서 다음과 같이 또는 c++14, c++17 등 상위버전을 설정했지만 계속 에러메시지가 보인다.
"C_Cpp.default.cppStandard": "c++11",

# 이밖에도 c++11 의 auto type 사용할 수 없다는 다음의 에러가 발생한다.
'auto' type specifier is a C++11 extension [-Wc++11-extensions]

# 해결방법
# vscode > open settings (JSON) > 에서 다음과 같이 clang 컴파일러의 -std=c++11 을 명시하면 된다.
"clang.cxxflags": [
    "-std=c++11"
]

apache httpd 모듈 사용자 요청 scheme 파악

# apache httpd 에 사용 할 C/C++ 모듈 예)mod_ysoftman.so 개발시
# ap_hook_handler 를 통해 request_rec* req (사용자 요청 레코드)를 받을 수 있다.
# scheme(http, ftp,..) 종류를 파악해보자
# httpd.h 에 명시된 매크로 사용 하면 된다.(v2.2 이상)
ap_run_http_scheme(req)

# 그런데 gtest 빌드시 다음 에러가 발생한다.
undefined reference to `ap_run_http_scheme'

# gtest 컴파일은 -lapreq2 -lapr-1 라이브러리만 링크하게 되는데
# ap_run_http_scheme 와 같이 ap_ 로 시작하는 함수들은
# httpd daemon 루틴으로 httpd 데몬 실행 환경에서만 사용할 수 있다.
# 다음 exp 파일에서 각각 라이브러리에서 사용하는 함수들을 확인할 수 있다.
apache/modules/httpd.exp
apache/lib/apr.exp, aprutil.exp

# httpd library 를 -l 링크하지 않으면 ap_xxx 함수들을 찾을 수 없게 된다.


##########


# 삽질~
# ap_xx 대신 apr(apache runtime) 라이브러리에서 비슷한 함수을 찾아 봤다.
# apr 라이브러리에서는 apr_uri_parse() 로 scheme 를 알 수 있다.
# 하지만 req->uri, unparsed_uri,.. 등을 찍어보면 scheme 정보가 없다.
fprintf(stderr, "ysoftman unparsed_uri %s\n", req->unparsed_uri);
fprintf(stderr, "ysoftman uri %s\n", req->uri);
fprintf(stderr, "ysoftman the_request %s\n", req->the_request);
fprintf(stderr, "ysoftman path_info %s\n", req->path_info);
fprintf(stderr, "ysoftman args %s\n", req->args);
fprintf(stderr, "ysoftman protocol %s\n", req->protocol);
fprintf(stderr, "ysoftman method %s\n", req->method);
fprintf(stderr, "ysoftman content_type %s\n", req->content_type);
fprintf(stderr, "ysoftman user %s\n", req->user);
fprintf(stderr, "ysoftman ap_auth_type %s\n", req->ap_auth_type);

# 따라서 다음과 같이 req->pool 에서 찾는게 아니라 scheme 이 포함된 url 스트링을 주고 이를 파싱하는데만 쓸 수 있다.
apr_uri_t parsed_uri;
apr_status_t ret = apr_uri_parse(req->pool, "http://ysoftman.com", &parsed_uri);
if (ret != APR_SUCCESS)
{
    return "";
}
fprintf(stderr, "ysoftman parsed_uri.scheme %s\n", parsed_uri.scheme);


##########


# 해결방법 - gtest 에서 ap_run_http_scheme 을 찾지 않도록 자체 구현하면 된다.
# gtest 코드에서 다음과 mockup 함수로 선언하고
# MOCK_CONST_METHOD + 파라미터 개수 + (함수명, 리턴타입())
MOCK_CONST_METHOD0(scheme, std::string());

# cpp 파일에 C 스타일로 컴파일도록하고
# 의미없는 ap_run_http_scheme() 를 구현해놓는다.
#ifdef __cplusplus
extern "C" {
#endif
char *ap_run_http_scheme(request_rec *r)
{
return NULL;
}

#ifdef __cplusplus
}
#endif

zsh - prezto 1라인 문자 출력 문제

# zsh 기반의 prezto 쉘을 사용하는데
# 줄바꿈(\n)이 없는 한줄 문자열을 출력할때 보이지 않는 문제가 있다.
# 다음과 같이 \n 없이 실행하면 문자열이 출력되지 않는다.

# -n(newline 없이 출력)옵션을 사용하면 출력되지 않는다.
echo -n "ysoftman"

# c 테스트 코드(bash 에서는 ! 를 빼자)
# 명시적으로  flush 해도 출력되지 않는다.
echo -e "#include <stdio.h> \n int main() { printf(\"abcdefg\"); fflush(stdout); return 0;}" >! zz.c && gcc zz.c && ./a.out

# go 테스트 코드
echo -e "package main\n
import \"fmt\"\n
func main(){\n
        fmt.Print(\"AA\")\n
}" >! zz.go && go run zz.go


# 위 명령어 뒤에 && echo 하면 제대로 나온다.
# curl로 1줄짜리 응답을 받는 경우에도 똑같은 상황이다.
# oh-my-zsh, bash 환경에서는 문제가 없고, 다른 서버의 prezto 에서도 잘된다.

# 원인은 no_prompt_cr (prompt_cr 사용하지 않는다는 의미) 설정해 발생한다.
setopt no_prompt_cr

# prompt_cr 은 zsh 에서 사용하는 옵션으로 cr(carriage return) 을 출력한다.
http://zsh.sourceforge.net/Doc/Release/Options.html#index-NO_005fPROMPT_005fCR

# 다시 prompt_cr 을 사용하면 임시로 되긴 한다.
setopt prompt_cr

# 그런데 같은 이슈가 등록되어 있었고, 이미 해결된 상태다.
https://github.com/sorin-ionescu/prezto/issues/1473
https://github.com/sorin-ionescu/prezto/issues/1426

# 해결은 최신 zprezto 를 설치하면 된다는것.
# prezto 설치 스크립트로 다시 설치하자 상황종료~
https://github.com/ysoftman/myenv
zsh ./installprezto.zsh

C++ vector 네이밍 실수?

c++ STL(Standard Template Library) 에서 많이 사용하는 vector 의 이름은 STL 을 Alex's lesson 가 기존 C 에 내장된 배열(array)과 구분하기 위해 선택한것이라고 한다. 그런데 수학에서 고정된 숫자 순서를 vector 라는 용어로 사용한다고 하니 동적길이를 가지는 C++ STL 을 생각하면 혼동이 될것 같다.
처음 vector 를 알았을때 이름을 왜 동적배열 같은걸로 짖지 않았을까 의문이 들었는데..
아래 글을 보면 Alex's lesson 자신도 네이밍 실수를 인정하고, 이름 질때 신중해야한다고 조언도 한다.ㅋ

원문 : https://stackoverflow.com/questions/581426/why-is-a-c-vector-called-a-vector/758548#758548

It's called a vector because Alex Stepanov, the designer of the Standard Template Library, was looking for a name to distinguish it from built-in arrays. He admits now that he made a mistake, because mathematics already uses the term 'vector' for a fixed-length sequence of numbers. Now C++0X will compound this mistake by introducing a class 'array' that will behave similar to a mathematical vector.

Alex's lesson: be very careful every time you name something.


linux write atomic

리눅스에서 멀티 프로세스가 하나의 파일에 쓰기 작업을 할 경우 어떻게 될까?
우선 파일쓰기시 fprintf, fwrite, 등의 C standard library 에서 제공하는 함수를 사용할 수 도 있고 write 와 같은 시스템 함수를 사용할 수 도 있다.
fprintf 의 경우 내부 버퍼링을 하고 write 시스템 콜을 수행하게 된다.

참고

write 함수의 경우 파일이 추가 가능 모드로 열렸다면 파일의 끝 offset 과 쓰기 연산은 atomic 하게 동작한다고 한다.
POSIX.1(.1 은 C standard library 를 규정, .2 shell 관련 규정)에 따라 SSIZE_MAX 까지 쓸 수 있다고 한다. 

SSIZE_MAX 는 /usr/include/bits/posix1_lim.h 에 정의 되어 다음과 같이 정의 되어 있다.
#ifndef SSIZE_MAX
# define SSIZE_MAX  LONG_MAX
#endif

LONG_MAX 는 /usr/include/limits.h 에는 /bits/posix1_lim.h 를 포함하고 있고 다음과 같이 정의 LONG_MAX 가 정의 되어 있다.
#  if __WORDSIZE == 64
#   define LONG_MAX 9223372036854775807L
#  else
#   define LONG_MAX 2147483647L
#  endif

64비트 머신에서 다음과 같이 프로그래밍 해보면
#include <stdio.h>
#include <limits.h>
int main()
printf("SSIZE_MAX : %ld\n", SSIZE_MAX);
return 0;
}

SSIZE_MAX : 9223372036854775807 결과를 보인다.

결국 다음과 같이 write 로 파일 쓸때는 64비트머신에서 거의 무한대로 쓸 수 있는데
On Linux, write() (and similar system calls) will transfer at most 0x7ffff000 (2,147,479,552) bytes, returning the number of bytes actually transferred.(This is true on both 32-bit and 64-bit systems.)

문제는 3.14 이전 커널에서 atomic 하지 않다는 문제가 있다고 한다.

BUGS
Among the APIs subsequently listed are write() and writev(2).  And the effects that should be atomic across threads (and processes) are updates of the file offset.  However, on Linux before version 3.14, this was not the case: if two processes that share an open file description (see open(2)) perform a write() (or writev(2))at the same time, then the I/O operations were not atomic with respect updating the file offset, with the result that the blocks of data output by the two processes might (incorrectly) overlap. This problem was fixed in Linux 3.14.

참고 리눅스 바닐라 커널(kernel) http://man7.org/linux/man-pages/man2/write.2.html

여기서 파일 오동작의 경우가 2개가 있는데
interleave(끼우다) : 데이터 쓰는중에 다른 데이터가 껴들어간것
overlap(겹치다): 데이터를 쓰는중 다른 데이터가 덮어 써지는것
위에서 설명한건 offset 이 atomic 하지 않아 overlap 된다는것.
uname -r 로 확인해보면 3.10.0 버전을 사용하는데 어떻게 될지...?
멀티 쓰레드 환경에서 하나의 파일에 동시 쓰기 테스트

https://github.com/ysoftman/test_code/blob/master/cpp/multi_thread_write_same_file.cpp
로 테스트 하니 멀티쓰레드에서는 문제가 없고 멀티 프로세스 환경에서 fprintf()를 사용시문제가 발생한다.

리눅스 버전 의미 참고 http://unix.stackexchange.com/questions/9743/numbering-convention-for-the-linux-kernel

테스트 환경은 centos7 이고 커널버전은 3.10.0-514.6.2.el7.x86_64
centos 에서는 기본 리눅스 바닐라 커널(3.10.0)을 베이스로 하고 이슈가 발생된 부분은 패치 적용하는 방식을 취한다고 한다. 그래서 3.10 버전이지만 위와 같은 오래전 이슈는 이미 수정되어 반영된것으로 보인다.

vscode c++ formatting 적용하기

# vscode cpp extenstion 을 설치하고 코드 포맷팅을 하면 엉뚱하게 포맷팅이 된다.
# 이유는 포맷팅 환경이 설정되어 있지 않아서이다.
# 우선 clang-format 을 설치하자.
brew install clang-format

# 사용자설정(settings.json) 을 다음과 같이 설정한다.
"C_Cpp.clang_format_path": "/usr/local/bin/clang-format",

# 현재 프로젝트에 .clang-format 파일을 읽어 들인다.
"C_Cpp.clang_format_style": "file",

# format_style 실패시 기본 셋팅(Visual Studio, LLVM, Google, Chromium, Mozilla, WebKit)
"C_Cpp.clang_format_fallbackStyle": "Visual Studio"

# 참고

boost 빌드

# boost 최신 파일 다운
wget https://sourceforge.net/projects/boost/files/boost/1.62.0/boost_1_62_0.tar.gz

# 또는
curl -OLv https://sourceforge.net/projects/boost/files/boost/1.62.0/boost_1_62_0.tar.gz

# 압축풀고 bootstrap.sh 실행
tar zxvf boost_1_62_0.tar.gz
cd boost_1_62_0/
./bootstrap.sh

# b2, bjam 등의 생성되며, b2 에 옵션 프로퍼티 타겟으로 빌드 후 설치
# b2 [options] [properties] [targets]
# target : install
# option : /usr/local에 설치(default)
# properties : gcc컴파일러, c++11사용, 디버그, 64비트머신, 멀티쓰레드
sudo ./b2 --prefix="/usr/local" toolset=gcc cxxflags="-std=c++11" variant=debug address-model=64 threading=multi install

# 타겟 파일 삭제
# 옵션 설명은 ./b2 --help
./b2 --clean-all

# 라이브러리 경로 추가
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib

# 참고
http://www.boost.org/build/doc/html/bbv2/overview/invocation.html
http://stackoverflow.com/questions/18452723/change-boost-build-jamfile-for-c11-support


#####


# 패키지 관리자를 이용한 boost 설치
# centos
sudo yum install boost boost-devel

# ubuntu
sudo apg-get install libboost-all-dev

vscode c++ 코드 네비게이션 하기

vscode c++  파일을 열었을때 코드 정의 가기(네비게이션)이 안될 수 있다.
c++ 기본 라이브러리 외에 커스텀 라이브러리를 사용는 경우 그 include 경로를 다음과 같이 지정해야 한다.

0. cpptools 로 익스텐션 검색해 설치해야한다.
1. include 문에서 경로를 찾을 수 없으면 구불구불한 녹색 밑줄이 표시된다.
2. 밑줄 -> 전구 -> "Add include path to settings" 클릭
3. .vscode/c_cpp_properties.json 이 생성된다.
4. mac/linux/win32 환경에 따라 includePath 에 경로를 추가한다.


참고 https://code.visualstudio.com/docs/languages/cpp

DOS Turbo C

ms-dos 에서 내게 c 프로그래밍의 문을 열어준 borland turbo c 2.0 지금봐도 정말 잘 만들었다. 
프로그래밍 언어는 microsoft gw-basic 을 먼저 접했지만 뭔가 실행 바이너리(.exe)를 만들고 학창시절 더 재미를 느꼈던건 turbo-c 였다.

dosbox 환경에서 Borland Turbo C 실행 화면

컴파일 : F9
실행 : Ctrl + F9 (dosbox 에서 종료 단축키와 같기 때문에 dosbox에는 단축키를 사용하지 말자.)
도스 실행화면 보기 : Alt + F5


플로피디스크 이미지(.img) 파일의 경우 7zip 프로그램으로 열 수 있다.

C Coding Convention and Naming Notation

# BSD Convention(style)
# 버클리 대학교 Eric Allman 프로그램머의 이름을 따 Allman 스타일이라고도 한다.
# 함수와 조건문 반복문 모두 중괄호 시작 위치가 뉴라인에서 시작한다.
# 장점: 중괄호의 시작 위치가 일관적이라 코드 읽기가 쉽다.
# 단점: 라인 수 증가

int funcA()
{
 if (condition > 0)
 {
  result = 1 + 1;
 }
}

# K&R(Kernighan and Ritchie) Convention(style)
# C 언어를 만드신 두분의 이름을 딴 스타일로
# 함수에는 BSD 와 같이 중괄호 시작위치가 뉴라인에서 시작하지만
# 조건문과 반복문에서는 공백후 시작한다.
# 장점: 코드량(라인수) 감소
# 단점: 중괄호 시작 위치에 일관성이 없어 BSD 에 비해 코드 읽기가 어렵다.
int funcA()
{
 if (condition > 0) {
  result = 1 + 1;
 }
}

# 참고로 함수 이름 과 { 시작 전에 파라미터를 선언하는 것으로
# K&R(Kernighan and Ritchie) old(obsolete)스타일로 거의 사용하지 않는다.
int func1(int_param, char_param)
int int_param;
char *char_param;
{
    printf("%s int_param=%d char_param=%s\n", __FUNCTION__, int_param, char_param);
    return 0;
}

# 기타 스타일
https://en.wikipedia.org/wiki/Indentation_style

# 헝가리언 표기법
# MS 프로그래머인 Charles Simonyi  가 사용한 이름 표기 방식으로 특수한 prefix 를 사용한다.
bool bFlag;
char *pName;
char cChar;
char szName[10];
int nIndex;
float fNum;
class CClass

# 카멜(Camel) 표기법
# 소문자로 시작해서 단어 사이를 대소문자로 구별한다.
void myTestFunction() {}

# 파스칼(Pascal) 표기법
# 첫번째 문자를 대문자로 시작한다.
void MyTestFunction() {}

Visual C++ 2008 이상 Release 모드에서 디버깅하기

Release 모드에서 디버깅하려면 다음과 같이 설정한다.

프로젝트 속성 -> 구성속성 -> C/C++ -> 일반 -> 디버깅 정보 형식 -> 프로그램 데이터베이스(/Zi)
프로젝트 속성 -> 구성속성 -> C/C++ -> 최적화 -> 최적화 -> 사용안함(/Od)
프로젝트 속성 -> 구성속성 -> 링커 -> 디버깅 -> 디버그 정보 생성 -> 예(/DEBUG)

C++ 헤더파일(.h) 중복 include 방지 방법 장단점

# 헤더파일(.h)이 중복 포함되어 불필요한 컴파일 시간이 늘어나는 것을 막기 위해 2가지 중복 포함 방지 방법이 있다.
# 첫번째 .h 중복 포함 방지
# 컴파일러에 따라 지원(Visual C++ 5.0 이상)안될 수 있지만 간결하게 사용할 수 있다.
#pragma once

# 두번째 .h 중복 포함 방지
# 코딩 줄 수가 첫번째 방법보다 많지만 표준이기 때문에 컴파일러에서 상관없이 사용할 수 있다.
#ifndef __YSOFTMAN_H__
#define __YSOFTMAN_H__
...
#endif

Visual C++ 컴파일 에러(xxx.sbr' 파일을 열 수 없습니다.: No such file or directory) 해결하기

[빌드시 다음과 같은 컴파일 에러가 발생하였을때]
xxx.sbr' 파일을 열 수 없습니다.: No such file or directory

[해결방법]
C/C++ -> 찾아보기 정보 -> 찾아보기 정보 사용 -> 없음

64bit 데이터 모델에 따른 int , long 크기 차이

참고: http://www.unix.org/version2/whatsnew/lp64_wp.html
데이터모델에 따라 int , long 의 크기가 다르다

DataModel    char    short    int    long    long long    pointers/size_t    OS(64bit)
LP64             8        16        32    64        X              64                      Unix, Solaris, Linux, Mac OS
LLP64           8        16        32    32        64             64                      MS-Windows
ILP64            8        16        64    64        X              64
LP64 는 long 과 pointer 만 64bit 라는 표시
LLP64 는 long long 과 pointer 만 64bit 라는 표시
ILP64 는 int 와 long 과 pointer 만 64bit 라는 표시

OpenCV 빌드하기

# 윈도우 빌드
# CMake download
http://www.cmake.org/

# OpenCV download
http://opencv.org/

# CMake 실행
# Where is the source code: 항목에 소스 경로 명시
# Where to build the binaries: 결과파일이 생성될 경로 명시
# Configure 실행하여 컴파일러 선택 후 finish
# Configure Done 후 Generate 실행하면 .sln .vcproj 등의 파일이 생성된다.
# VS2008 의 경우 OpenCV.sln 를 열고 일괄빌드에서
# ALL_BUILD 프로젝트 빌드하면
# bin => *.dll *.pdb 생성됨
# lib => *.lib *.exp 생성됨


#####


# 리눅스 빌드
# CMake 설치
sudo yum install cmake

# OpenCV download
wget http://downloads.sourceforge.net/project/opencvlibrary/opencv-unix/2.4.2/OpenCV-2.4.2.tar.bz2?r=http%3A%2F%2Fopencv.org%2Fdownloads.html&ts=1344324014&use_mirror=cdnetworks-kr-2

# OpenCV 압축 풀기
tar -jxvf OpenCV-2.4.2.tar.bz2

# OpenCV-2.4.2 위치(CMakeLists.txt 위치)에서
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local .

# Make파일이 생성되면
make -j10
sudo make install
/usr/local/lib 에 *.so 파일이 생성됨

Visual C++ 프로젝트 속성에서 사용하는 매크로에 대한 설명

출처 : MSDN
프로젝트의 속성 페이지 대화 상자에서 문자열을 입력할 수 있는 모든 부분에 다음과 같은 매크로를 사용할 수 있습니다. 이 매크로는 대/소문자를 구분하지 않습니다.


$(RemoteMachine)
 디버그 속성 페이지에서 원격 컴퓨터 속성의 값으로 설정합니다. 자세한 내용은 C/C++ 디버그 구성에 대한 프로젝트 설정 변경을 참조하십시오.

$(References)
 프로젝트에 추가된 참조 목록(세미콜론으로 구분)

$(ConfigurationName)
 현재 프로젝트 구성의 이름(예: "Debug")

$(PlatformName)
 현재 프로젝트 플랫폼의 이름(예: "Win32")

$(Inherit)
 프로젝트 빌드 시스템에서 작성한 명령줄에 상속된 속성이 나타나는 순서를 지정합니다. 기본적으로 상속된 속성은 현재 속성의 맨 뒤에 나타납니다.1

$(NoInherit)
 상속될 모든 속성이 상속되지 않도록 합니다. 형제 수준에서도 실행되지 않도록 하려면 $(StopEvaluating)을 사용합니다. $(NoInherit)를 사용하면 동일한 속성에 대한 모든 $(Inherit)가 무시됩니다.1

$(StopEvaluating)
 실행 체인에 있는 매크로 실행을 즉시 중지합니다. $(StopEvaluating) 뒤에 나오는 모든 값은 매크로의 실행 값에 나타나지 않습니다. $(StopEvaluating)이 $(Inherit) 앞에 오는 경우 실행 체인의 현재 위치에 있는 상속된 값이 매크로 값에 연결되지 않습니다. $(StopEvaluating)은 $(NoInherit) 기능의 상위 집합입니다.

$(ParentName)
 이 프로젝트 항목을 포함하는 항목의 이름. 부모 폴더 이름이나 프로젝트 이름입니다.

$(RootNameSpace)
 응용 프로그램을 포함하는 네임스페이스(있을 경우)

$(IntDir)
 중간 파일에 지정된 디렉터리 경로로서 프로젝트 디렉터리에 대해 상대적인 경로. 이 경로는 중간 디렉터리 속성의 값이 됩니다.

$(OutDir)
 출력 파일 디렉터리의 경로로서 프로젝트 디렉터리에 대해 상대적인 경로. 이 경로는 출력 디렉터리 속성의 값이 됩니다.

$(DevEnvDir)
 드라이브 + 경로로 정의되는 Visual Studio .NET의 설치 디렉터리로서 뒤에는 백슬래시(\)가 붙습니다.

$(InputDir)
 드라이브 + 경로로 정의되는 입력 파일의 디렉터리로서 뒤에는 백슬래시(\)가 붙습니다. 해당 프로젝트가 입력 파일인 경우 이 매크로는 $(ProjectDir)와 같습니다.

$(InputPath)
 드라이브 + 경로 + 기본 이름 + 파일 확장명으로 정의되는 입력 파일의 절대 경로 이름. 해당 프로젝트가 입력 파일인 경우 이 매크로는 $(ProjectPath)와 같습니다.

$(InputName)
 입력 파일의 기본 이름. 해당 프로젝트가 입력 파일인 경우 이 매크로는 $(ProjectName)과 같습니다.


$(InputFileName)
 기본 이름 + 파일 확장명으로 정의되는 입력 파일의 파일 이름. 해당 프로젝트가 입력 파일인 경우 이 매크로는 $(ProjectFileName)과 같습니다.

$(InputExt)
 입력 파일의 파일 확장명. 파일 확장명 앞에는 '.'이 붙습니다. 해당 프로젝트가 입력 파일인 경우 이 매크로는 $(ProjectExt)와 같습니다.

$(ProjectDir)
 드라이브 + 경로로 정의되는 프로젝트의 디렉터리로서 뒤에는 백슬래시(\)가 붙습니다.

$(ProjectPath)
 드라이브 + 경로 + 기본 이름 + 파일 확장명으로 정의되는 프로젝트의 절대 경로 이름.

$(ProjectName)
 프로젝트의 기본 이름.

$(ProjectFileName)
 기본 이름 + 파일 확장명으로 정의되는 프로젝트의 파일 이름.

$(ProjectExt)
 프로젝트의 파일 확장명. 파일 확장명 앞에는 '.'이 붙습니다.

$(SolutionDir)
 드라이브 + 경로로 정의되는 솔루션의 디렉터리로서 뒤에는 백슬래시(\)가 붙습니다.

$(SolutionPath)
 드라이브 + 경로 + 기본 이름 + 파일 확장명으로 정의되는 솔루션의 절대 경로 이름.

$(SolutionName)
 솔루션의 기본 이름.

$(SolutionFileName)
 기본 이름 + 파일 확장명으로 정의되는 솔루션의 파일 이름.

$(SolutionExt)
 솔루션의 파일 확장명. 파일 확장명 앞에는 '.'이 붙습니다.

$(TargetDir)
 드라이브 + 경로로 정의되는 빌드용 기본 출력 파일의 디렉터리로서 뒤에는 백슬래시(\)가 붙습니다.

$(TargetPath)
 드라이브 + 경로 + 기본 이름 + 파일 확장명으로 정의되는 빌드용 기본 출력 파일의 절대 경로 이름.

$(TargetName)
 빌드용 기본 출력 파일의 기본 이름.

$(TargetFileName)
 기본 이름 + 파일 확장명으로 정의되는 빌드용 기본 출력 파일의 파일 이름.

$(TargetExt)
 빌드용 기본 출력 파일의 파일 확장명. 파일 확장명 앞에는 '.'이 붙습니다.

$(VSInstallDir)
 Visual Studio .NET을 설치한 디렉터리.

$(VCInstallDir)
 Visual C++ .NET을 설치한 디렉터리.

$(FrameworkDir)
 .NET Framework를 설치한 디렉터리.

$(FrameworkVersion)
 Visual Studio에서 사용되는 .NET Framework의 버전. $(FrameworkDir)와 함께 사용하면 Visual Studio에서 사용되는 .NET Framework 버전의 전체 경로를 나타냅니다.

$(FrameworkSDKDir)
 .NET Framework를 설치한 디렉터리. .NET Framework는 Visual Studio .NET과 함께 또는 별도로 설치할 수 있습니다.

$(WebDeployPath)
 웹 배포 루트에서 프로젝트 출력이 속한 상대 경로. RelativePath와 같은 값을 반환합니다.

$(WebDeployRoot)
 <localhost>의 절대 경로(예: c:\inetpub\wwwroot).

$(SafeParentName)
 올바른 이름 형식에서 바로 상위 항목의 이름. 예를 들어, 폼은 .resx 파일의 상위 항목입니다.

$(SafeInputName)
 올바른 클래스 이름으로 정의되는 파일 이름(확장명은 제외).

$(SafeRootNamespace)
 프로젝트 마법사에서 코드를 추가할 네임스페이스 이름. 이 네임스페이스 이름은 올바른 C++ 식별자에 사용할 수 있는 문자만 포함합니다.

$(FxCopDir)
 fxcop.cmd 파일의 경로. fxcop.cmd 파일은 모든 Visual C++ 버전에 설치되어 있지는 않습니다.

C++ JSON Library BenchMark

C++ 용 JSON 라이브러를 벤치마크한 블로그
http://lijoblogs.blogspot.com/2011/11/comparison-and-benchmark-of-c-json.html