[VS2008] R6030 - CRT not initialized 에러 └ 기 타

Debug모드로 컴파일 할때는 잘만 실행되던 소스코드가

막상 Release로 컴파일 하니까 실행이 되지 않는 황당한 일이 일어났다

급한 마음에 구글링을 했는데, 라이브러리 링크 순서를 바꿔서 해결했다는 등의

나랑 전혀 관계없는 이야기만 있었다...

msdn에 검색해 본 결과도 다음과 같은 내용 밖에 없고...


링커 스위치 /ENTRY를 사용하여 기본 시작 주소를 재정의한 경우에 이 오류가 발생 할 수 있다고 하는데...

재 정의한 기억도 없고, 아예 msdn에서 언급한 WinMainCRTStartup  으로 ENTRY를 설정해도 해결이 안되었다...

그러다가... Code Generation 옵션에 Runtime Library를 

Multi-threaded DLL (/MTd) 에서 Multi-threaded (/MT)로 바꾸니까...

어처구니 없게도 실행이 되는 것이다 -ㅂ-;;

결국 정확한 원인은 무엇이었던 것일까

혹시 비슷한 문제로 고민하시는 분들 위의 방법을 시도해 보시기 바랍니다

VS2008 기준 Project Properties -> C/C++ -> Code Generation 의 Runtime Library를 바꿔보시기 바랍니다

[XCode] Include Path 설정 정 보

DevIL 라이브러리를 설치했는데... xcode에서 include path를 못 잡고 있길래 한참 삽질...
Project 정보를 찾다가 뭔가 나와서 적용해 보니 성공!!
잊어버리기 전에 기록해 둔다..
XCode 왼쪽에 Group & Files 에 보면 프로젝트 리스트가 있다
프로젝트 이름에 마우스 오른쪽 클릭을 하고 [ Get Info ] 를 누른다
Build 탭에서 밑으로 내려서 찾아도 되고... 옆에 검색창에 검색을 하자
header search paths
그러면 밑에 Setting 란에 Header Search Paths라고 있다
설정 부분을 더블 클릭하면 아래와 같이 추가 할 수 있는 윈도우가 뜬다
왼쪽 아래 + 버튼로 추가 하거나 - 버튼으로 삭제할 수 있다
Recursive 버튼은 이하 디렉토리를 재귀적으로 탐색할 것인지 여부를 결정하는 것
직접 입력할 경우 Path와 Path는 스페이스로 구분되고,
해당 디렉토리를 Recursive하게 탐색하고자 한다면 **를 붙여주면 된다
가령 /usr/local/include/ 밑을 Recursive하게 탐색하고자 한다면...
/usr/local/include/-* 
이렇게 작성하면 된다. 자동 추가 윈도우로 넣으면 알아서 정리되어서 들어간다

[C/C++] 2차원 배열의 동적 할당 └ C/C++

때때로 2차원 배열을 동적으로 할당하여 써야 할 때가 많습니다

막 C/C++ 언어를 배웠을 무렵에는 아무런 의심없이 당연한 듯이 더블 포인터를 이용했지요

아마 다들 한번씩은 다음과 같이 써보셨을 거라고 생각합니다

int** pData = new int* [ ROW ];

for( int i=0; i < ROW; i++ )
{
        pData[i] = new int [ COLUMN ];
}

이 방법에는 여러 단점이 존재하게 됩니다

먼저, 할당을 여러번 사용해야 한다는 점이 있지요

행(Row)의 수 + 1만큼의 new 또는 malloc을 사용해서 공간을 할당받아야 하지요

또한 저렇게 할당 될 경우, 아래 그림처럼 데이터들이 열마다 서로 다른 공간에 할당되어 있기 때문에

전체 초기화도 행마다 memset을 해줘야 하는 번거로움이 있기 마련입니다

























그러다가 1차원 배열로 할당해서 사용하게 되었지요

아무래도 이쪽이 이득이 많다고 생각해서 인 것 같습니다

하지만 1차원 배열은 index를 계산해야 하는 번거로움이 있다고 느끼실지도 모릅니다

바로 이런식으로 말이지요

pData[ r * COLUMN + c ] = data[r][c];



그래서 요즘은 이렇게 쓰기도 합니다

메모리를 일부 희생시킴으로 해서 접근성을 높여본 것이지요

int *pData;
int **pDouble;

pData     = new int [ ROW * COLUMN ];
pDouble  = new int* [ ROW ];

forint i=0; i < ROW; i++ )
{
        pDouble[i] = &( pData[ i * COLUMN ] );
}

위의 2 방법을 절충(?)시킨 방법입니다만... 그럭저럭 쓸만합니다

뭐 이런게 팁이라고 할만한 내용은 아닙니다만...

일단, 할당이 한번 더 늘어난다는 점이 있지만,

필요에 의해서 초기화 / 복사 등을 이용할 때에는 pData 포인터를 사용하시고

row, column으로 데이터에 접근하실 때는, pDouble 포인터를 이용하면 됩니다



어떻게 보면 전혀 쓸모없는 (오히려 안좋은) 방법일 수도 있지만...

사용하기에 따라서는 한번씩은 써볼만한 것 같습니다

[HTML5] Canvas Transform과 Path └ HTML5

이전에 Canvas2D에서 Transform에 대해서 설명하면서 

마지막에 Transform은 그리려는 객체에 적용되지 않고, Canvas자체에 적용된다고 했다

다시말하면 아래 그림과 같이 생각하면 된다


















위 그림에서처럼 만약 Translate를 적용시킨다면,

사각형을 이동해서 그리는 것이 아닌, Canvas 자체를 이동시킨다

이것은 회전이나, 다른 Transform도 마찬가지이다.

이를 확실하게 알 수 있는 방법은 바로 Path를 이용해서 그림을 그려보는 방법이다

아래와 코드와 같이 Path를 이용하여 별 모양을 그려보도록 하자

function drawStar( pContext )
{
// pContext는 Canvas에서 getContext("2d")로 얻어온 그 것

var vtx = [
{ "x" :  0.000, "y" : -1.000 },
{ "x" :  0.951, "y" : -0.309 },
{ "x" :  0.588, "y" :  0.809 },
{ "x" : -0.588, "y" :  0.809 },
{ "x" : -0.951, "y" : -0.309 }
];
pContext.beginPath();
pContext.moveTo( vtx[0].x, vtx[0].y );
pContext.lineTo( vtx[2].x, vtx[2].y );
pContext.lineTo( vtx[4].x, vtx[4].y );
pContext.lineTo( vtx[1].x, vtx[1].y );
pContext.lineTo( vtx[3].x, vtx[3].y );
pContext.closePath();
pContext.stroke();
pContext.fill();
}

translate를 이용하여 화면 한 가운데 별을 그려보면 아래와 같다 (그림판으로 8배 확대했다)
















좌표에서 예상할 수 있듯이 확실하게 찍힌 검은색 2 by 2 pixel과 

Anti-alias 효과를 위한 듯이 보이는 주변 회색 pixel들이 보인다

위 별의 좌표는 반지름이 1인 원 위의 5개의 점을 선으로 이은 것이다.

만일 Transform이 각 그려지는 객체에 적용된다면, 만약 Scale을 통해서 5배로 확대할 경우,

약 10 Pixel 정도의 크기를 가진 별이 그려져야 옳은 결과다

하지만 아래 그림을 보자 ( 5배 확대 후 사진 - 역시 그림판으로 8배 확대 )























쭉 새어보면 세로 픽셀이 25픽셀 20 픽셀이 넘어간다 어떻게 된 일일까?

바로 Canvas자체를 Scale하기 때문이다.

다시 제일 처음 확대하기 전의 별 그림을 기억해 보자

회색 pixel까지 합쳐서 세로가 약 5 pixel 정도가 된다

그것의 5배 25 pixel 이렇게 계산하면 맞아 떨어진다

즉, 앞서 말했듯이 그려지는 객체에 대해서 확대가 일어나는 것이 아닌,

Canvas 자체의 크기를 늘리는 것이다

이런 부분은 당연한 이야기지만, Document를 잘 찾아보면 언급되어 있는 부분이다

다만, Path 사용 중에 이 사실을 깜빡하는 경우가 있어서 이렇게 예를 보이며 작성해 보았다

따라서 저렇게 좌표를 이용해서 Path( 결국은 polygon )을 그려준다면

좌표 변환을 적용하여 그려주는 것이 좋다

이동이나, 회전 등은 그다지 주의하지 않아도 될 법 하지만

위에서 본 Scale (확대/축소)의 경우는 그 결과가 크게 차이가 나기 때문에

사용하는데 주의 해야 할 것이다

[HTML5] Canvas2D Transform └ HTML5

Canvas2D를 이용해야하는 작업이 생겨서 이것저것 만져보다가

나중에 다시 볼 때 가장 햇갈려할 것 같은 Transform부분을 정리한다

HTML5의 Canvas2D에는 다음과 같은 변환(Transform) 함수들이 있다

scale( x, y )
rotate( angle )
translate( x, y )
transform( a, b, c, d, e, f )
setTransform( a, b, c, d, e, f )

Canvas2D의 변환은 여타 3D API에서 제공하는 변환처럼 행렬로 처리된다

동차 좌표계를 포함 Canvas2D에 사용되는 행렬은 3 by 3 행렬이 된다.

변환 할 좌표를 x, y 라 하고, 최종 변환 된 좌표를 x', y' 이라고 했을 때,

변환 공식은 다음과 같다.


위쪽은 OpenGL을 많이 다뤄본 사람들에게 익숙한 행렬 곱 표현 방법이고

아래쪽은 DirectX를 많이 다뤄본 사람들에게 익숙한 행렬 곱 표현 방법이다

어느쪽이든 결과는 같다

눈치 빠른 사람은 눈치 챘으리라고 생각하지만

위 그림의 행렬에서 a, b, c, d, e, f는  위에서 설명한 함수 중

transform( a, b, c, d, e, f )
setTransform( a, b, c, d, e, f )

두 함수의 패러미터 a, b, c, d, e, f 이다

사실 상 변환에는 행렬에서 저 6개의 값만 사용된다.

많은 사이트 들이 

패러미터를 다음과 같이 정의한다

a :  scale-x
b :  skew-x
c :  skew-y
d :  scale-y
e :  translate-x
f  :  translate-y

틀린 말은 아니지만

이동 후 확대, 회전 후 이동 후 확대 등으 변환을 적용하려면 아무래도 위의 행렬 식으로 기억하는게 좋다

HTML5 에서의 변환 함수는 OpenGL과 비슷한 방식으로 동작한다

기본적으로 변환 행렬이 내부에 존재하고

setTransform()을 제외한 나머지 4개의 함수들이 호출될 때마다 행렬이 곱해진다

따라서 함수의 호출 순서는 변환에 영향을 준다

가령, 이동 후에 회전을 하고 싶다고 한다면

rotate() 함수를 먼저 호출하고 그 이후에 translate() 함수를 호출한다

가장 마지막에 호출된 함수부터 적용된다고 보면 된다

이동 후에 회전을 행렬 곱으로 나타내면 아래와 같을 것이다


함수 호출은 위 그림에서 첫번째 식의 형태를 취한다고 생각하면 된다

                                ┌ x ┐
함수를 호출할 때마다    |  y  |  앞에 행렬이 붙는다고 생각하면 된다
                                └ 1  ┘

순서 역시 [ x y 1 ] 벡터에 가까운 행렬부터 곱한다고 생각하면 된다

아래의 식이 어떻게 보면 더 직관적으로 보이긴 하지만

일단 표준 변환은 위의 식의 방식을 따른다는 점을 알아두자


마지막으로 setTransform() 함수는 행렬을 새로 곱하는게 아니라

변환 행렬을 패러미터 값으로 set 해버린다

따라서 변환 행렬을 초기화 하고 싶은 경우는 다음과 같이 호출하여 단위 행렬로 만들 수 있다

setTransform( 1, 0, 0, 1, 0, 0 );

왜 위와 같은지는 각 패러미터 자리를 제일 처음 식에 대입해 보라

또는 미리 변환 행렬을 계산해 놓고 때에 따라 바꿔서 적용해 볼 수도 있을 것이다


p.s. Transform의 경우 그려지는 객체에 적용되기 보다는 Canvas 자체에 적용된다는 사실을 알아두자

이게 어떤 결과를 가져다 주는지는 Path를 적용해 보면 알 수 있다

이부분은 따로 글을 작성하도록 하겠다


1 2 3 4 5 6 7 8 9 10 다음