오늘 당했던 일을 먼저....
솔루션의 프로젝트 구성은 이랬다.
 
프로젝트 1 : native C++ library (unmanaged code)
프로젝트 2 : wrapper Class (managed code) 
프로젝트 3 : C#
 
이때 wrapper class에서 native 함수를 호출하면 꼭 비관리코드에서 관리코드를 읽거나 쓰려고 했다는 예외가 발생했다.
호출되는 native c++ 함수에서 브레이크포인트를 걸어보니 그곳에서 걸리지 않았다.
그럼 호출 자체가 문제가 있다는건데 라이브러리를 바로 쓰는건데 왜 호출이 안되지?
마샬링으로 넘어오는 버퍼가 관리힙에 있는 건가? MSDN 설명으로는 그렇지는 않은데...
caller가 관리코드라 비관리코드 호출 후 caller로 돌아올 때 리턴코드가 영향을 끼치나?
관리코드에서는 비관리코드를 아예 호출할 수 없는건가? 등등으로 고민했다.
 
찾아봐도 딱히 답도 없고... 짜증이 머리 꼭대기에 오를때쯤. (아니, 이미 꼭대기에 올라 있었다)
별 기대없이 호출되는 native c++의 함수 내부를 비워봤더니 정상적으로 호출이 되는것이 아닌가!
왜?!?! 젠장!! 분명히 native c++ 함수 시작 부분에 걸어 놓은 브레이크포인트에는 안 걸렸는데!!
 
다시 확인해보니, 디버깅 모드로 시작과 동시에 그 브레이크포인트는 disable 되고 있었다... orz
뭐 아직 왜 예외 메시지가 그렇게 나오는지는 모르겠다.
예외의 원인은 널포인터 참조였는데, 예외가 저딴식으로 나오면 안되지... ㅡ_ㅡ;
난 이래서 try catch가 너무 싫다.
 
검색해보니 혼합모드 디버깅 자료는 널리고 널렸더라.. 제길.
요것때문에 시간 낭비한 걸 생각하면... ㅠ_ㅠ
 
혼합모드 디버깅
1. 시작 프로젝트의 설정에서 [비관리코드 디버깅 사용] 체크
2. native c++ 프로젝트 설정에서 [디버깅 형식] 을 네이티브 or 혼합 or 자동으로


싸이 블로그 백업 [하zi 2008.09.10 16:26]

프로그램에 문제가 생겼다.
왜 그런가 살펴봤더니 포인터가 NULL을 가르키고 있었다.
가벼운(?) 마음으로 살포시 NULL 체크를 해줬다. ^^v
버그 해결~
이라는 오류에 빠져들지 말자.
 
위에서 말한 상황에서는 현재의 상태를 수정한 것이지 문제를 수정한 것이 아니다.
위의 문제가 발생하고 있는 상태를 감염되었다고 한다.
물론 감염원은 현재의 상태를 만들어낸 결함이다.
 
디버깅을 할 때 주의할 점이 현재의 상태를 수정하려고 하지 말고, 현재의 상태를 만들어낸 결함을 찾아서 수정해야 한다는 것이다. 현재의 상태만 수정한다면 감염의 상태를 다음 프로세스에 넘겨주는 꼴이 된다.
디버깅을 할 때는 꼭 추적을 통해 감염원, 즉 결함을 찾아서 수정을 해야한다.
 
디버깅의 7단계
추적, 재현, 자동화, 근원 찾기, 집중, 격리, 정정
 
어떤 PPT를 보다가 나온건데, 뭐.. 난 저 단계를 아직 잘 모르겠다. (안봤다 ㅡㅡ;;)
하나 수정하는데 그렇게 많이 신경써야하나 싶다. 시간나면 함 보고...
 
내게 디버깅의 단계는 다음과 같다.
재현, 추적, 근원 찾기, 정정, 확인, 자동 검출 코드 추가.


싸이 블로그 백업 [하zi 2008.08.27 22:13]

이것에 대해 특별히 생각해 본적은 없었는데 오늘 생각해봤다.
대부분의 프로그래머나 일부 관심있는 사람들은 알겠지만 2진수와 16진수 사이의 변환은 쉽다.
 
0100100001110101 은 0x4875이다.
 
16은 2의 4승이므로 2진수 4개가 모여 하나의 16진수 숫자를 표현할 수 있다.
그래서 4개 단위로 나눠 0100 1000 0111 0101 로 나눈 후 4개씩 변환한다.
2진수 4자리가 각각 8,4,2,1로 그 비트가 1이면 그 수만큼 더하면 된다.
 
0100은 8x0 + 4x1 + 2x0 + 1x0 = 0x4
1000은 8x1 + 4x0 + 2x0 + 1x0 = 0x8
0111은 8x0 + 4x1 + 2x1 + 1x1 = 0x7
0101은 8x0 + 4x1 + 2x0 + 1x1 = 0x5
 
물론 나는 이런것에 대해 논리적으로 생각해보지 않았었고 경험상 알게된거다..
그럼 2진수나 16진수와 10진수 사이의 변환은 왜 어려운가?
 
위의 논리대로 계산이 가능하도록 하려면 다음을 만족해야한다.
10진수는 정수중 어떤 수의 몇승인가?
 
3진수와 9진수라면 3의 2승이므로 3을 두개 단위로 끊어서 계산하면 된다.
21 01 20 == 7 1 6
3진수와 27진수라면 3을 3개 단위로.
210 120 == 21 15
 
하지만 10은 그런 수가 없다.
혹시 숫자 10은 단순히 손가락이 열개이기 때문에 훌륭한 숫자인걸까?


싸이 블로그 백업 [하zi 2008.08.12 14:51]

p가 소수이고, m이 p와 서로소인 양수일 때, (페르마의 정리)
m(p-1)  mod p = 1 
 
p와 q가 소수일 때, n = p*q, 그리고 m과 n은 서로소일 경우, (오일러의 공식)
m(p-1) (q-1) mod n = 1 
 
이것이 어떻게 사용되는지도 조만간...


싸이 블로그 백업 [하zi 2008.07.14 19:03]

우리는 무언가 변화를 시도할 때 더 좋은 결과를 바라며 시행한다.
하지만 그 변화가 바로 좋은 결과를 내는 경우는 거의 없다.
대부분은 변화를 시도한 사람들이 혼돈(카오스)에 빠지는 경우가 생긴다.
자신이 익숙했던 것과의 사고 방법의 차이로 인해 당장에 업무효율이 떨어진다.
이때 도전자에게 한번의 선택의 순간이 다가온다.
현재 빠진 혼돈을 실패로 보고 다시 예전으로 되돌리느냐, 아니면 혼돈을 넘어서기 위해 사고의 전환을 시도하느냐이다.

<그림 1. 새티르 변화 모델>
 
낡은 현상태 : 지금 보기엔 불합리하며 개판이라 할 수 있겠지만, 그 당시엔 노력을 해서 만든 상태이므로 무의미 하지는 않다.
카오스 : 모든 사람들은 변화를 거부한다고 하므로 어찌보면 당연한 혼란상태. 하강곡선이 나타나며 생소한 것 때문에 전보다 상황이 더 나빠졌다고 여기게 된다.
실행과 융합 : 고통의 끝이 머지 않았다는 희망을 가지게 되면서 생각의 변화가 생긴다. 익숙해져가고 있다는 이야기.
새로운 현상태 : 처음에 새로운 것이라고 생각했던 것을 하고 있다면 이미 새로운 현상태에 도달한 것.
 
참조 목록
1 피플웨어 <30. 변화를 두려워 하지 말라>
2. http://www.poemi.net/346


싸이 블로그 백업 [2008.07.07 16:29]

"KDMLBRRQ"  이건 뭘까? 
 
이 글에서 이야기 할 시저의 암호화(encryption) 방법으로 암호화 된(encrypted) 암호문(ciphertext)이다. 
 
# 평문이란 암호화하기 전의 원래의 문장을 말한다.
# 일할때는 암호화라는 말은 거의 쓰이지 않는다. 온리 잉글리쉬... ㅡㅡ;;
 
명탐정 코난에서도 이것보다는 더 나은 암호화 방법을 썼던 것 같다. 음표였던가?
아주 단순한 암호화임에도 알아내기는 쉽지 않다.

시저는 이 암호화 방법을 사용하여 메시지를 전달하였고, 이 암호문을 풀기 위한 방법을 부하와 가족들에게 알려주었다.
 
암호화 함수는 우측 쉬프트였고 비밀키는 3이었다.
따라서 복호화 함수는 좌측 쉬프트다. ^^;;
 
글의 시작에 어울리는 쉬운 내용이라 설명 따위는 없다.
어차피 이건 암호학의 역사일 뿐...
 
근데 공개키에 대한 글 쓰려고 들어왔는데 지금 내가 왜 이걸 쓰고 있는걸까?
 
내가 이 블로그 만든 건 경력관리의 일환이라고~
근데 이런 쉬운 내용을 써놓으면 뭐하냐고~


싸이 블로그 백업 [2008.06.26 01:08]

class는 참조(System.Object), struct는 값(System.Value)
 
C++하다가 C#하면 헷갈리는 것 중 하나.
MyStruct myStructObj = new MyStruct(); // myStructObj는 스택에~
요로케 백날 해봤자 이건 힙에 생기지 않는다는거~
 
C++에서는 동적할당(즉, new나 malloc 등)을 받으면 무조건 힙에 쌓였지만 C#에서는 그 타입에 따라서 결정된다.
객체 생성 시 struct는 항상 스택에 생기고, class는 항상 힙에 생긴다.
 
물론 Boxing을 통해 struct도 힙에 위치시킬 수 있다.
잠깐... struct를 힙에 위치시킨다는 표현이 맞긴 맞는건가?

object myObj = myStructObj; // Boxing
 
이렇게 되면 MyStruct 구조체 데이터가 힙에 생기고 여기에 값을 복사한다. 그리고 그 참조를 myObj가 갖는다.
그럼 도대체 뭐냐?
struct가 힙에 있다고 해야하나?
 
그냥 참조는 힙에 존재하는 인스턴스의 참조라고 생각하자.
힙에 존재하는 인스턴스 자체는 값타입이고 참조타입이고 따위는 생각할 필요가 없는거다;; =_=
 
"값타입은 인스턴스 자체가 스택에, 참조타입은 인스턴스는 힙에 있고 참조가 스택에 있는거다." 라고 글 쓰다가 내맘대로 정리한 본인의 생각... 아님 말고... ㅡ_ㅡ;


싸이 블로그 백업 [2008.06.17 20:30]

C에서 동적할당은 다음과 같은 방법을 사용한다.
SMyStruct* pObject = (SMyStruct*) malloc(sizeof(SMyStruct));
if(pObject == NULL)
   return;

그리고 C에서 C++로 옮긴 프로그래머들은 자연스럽게 다음과 같은 코드를 쓰는 사람이 많다.
CMyClass* pObject = new CMyClass();
if(pObject == NULL)
   return;
 
나도 C를 하다가 C++를 배웠다. 물론 그 전에도 C++를 보긴 했었지만 내가 배우겠다는 의지를 갖고 본 것은 적어도 2년은 C프로그래머였던 때 이후다.

그래서 나 또한 위 코드에 대해 이상하다는 생각은 전혀 하지 못했다.

C++로 시작한 사람들은 왜 위의 코드가 잘못된 것인지 알까?


싸이 블로그 백업 [2008.06.16 13:21]

+ Recent posts