본문 바로가기

도구의발견

Conditional Break point with string(char*) - 특정 문자열일 경우 브레이크 포인트 활성화 하기

이전 포스팅([도구의발견] - Break point)에서 Visual Studio 디버거의 브레이크 포인트를 사용하는 방법에 대해서 알아 보았다. 그 중 브레이크 포인트에 조건을 걸어 주는 방법(Conditional breakpoint)에 대해서도 알아 보았는데, 오늘은 conditional breakpoint의 한계와 우회방법(?)에 대해서 알아보겠다.

[도구의발견] - Break point 의 내용 대로 하는 경우, 정수 값, 문자 값에 대해서는 조건문이 정상동작하지만, 문자열(char*, std::string) 같은 경우 전~혀 제대로 동작하지 않는다. 정확한 이유는 잘 모르겠지만, 그냥 나의 생각으로는 포인터 값을 주는 경우, 해당 포인터가 가리키고 있는 문자열을 비교하는 것이 아니라 포인터 자체의 주소 값을 비교하는 것 때문이 아닐까 추측한다(실제 동일한 주소를 가리키고 있는 포인터를 비교할 때는 해당 브레이크 포인트에 정상적으로 멈추는 것을 확인 했다).

그렇다면 특정 문자열일 경우에만 브레이크 포인트가 활성화 되게 하는 것은 불가능한가?
일단 답은 '가능하다' 이다.  

1. 문자열 비교의 결과값을 이용
만일 소스코드의 수정이 가능하다면, 특정 조건의 상수 문자열과 비교하는 코드를 추가하고 그 결과를 저장하는 변수를 생성한다. 그리고 그 변수의 값을 비교하는 방법이 있다. 

비교해야할 변수의 데이터 타입이 'char*' 인 경우는 아래와 같이 작성 될 수 있겠다 :

const char* name = "kukuta";

#ifdef _DEBUG // 디버깅용 코드
int ret = strcmp(name, "kukuta");
std::cout << "result : " << ret << std::endl;
#endif

std::cout << "name : " << name << std::endl;  // 여기서 name이 "kukuta" 일때만 멈추고 싶음

(물론 위의 코드는 상식으로 전혀 디버깅 할 필요가 없는 코드이긴 하지만..예제를 위해서 작성 했다. 태클은 노노!!)
#ifdef ~ #endif 내에 있는 코드는 실제 프로그램의 목적과는 아무런 상관 없는 오직 디버깅만을 위해 추가된 코드다. 저런식으로 코드를 추가한 뒤에 브레이크 포인트가 필요한 부분에 'ret' 변수의 결과 값이 0 혹은 0이 아닌지를 비교하는 조건문을 넣으면 된다.

또한 std::string을 사용하는 경우라면 간단한 if 문과 결과를 담는 bool 값으로 위의 코드가 대신 될 수도 있다.

2. 문자 하나 하나씩의 비교
위에서는 소스코드의 수정이 가능한 경우를 알아 보았다. 하지만 소스코드의 수정이 불가능한 경우도 종종 있다. 이럴 경우 어떻게 해야 할까? 그렇다. 문자열 하나하나를 다 비교해 해야 한다. 데이터 타입이 char* 의 경우라면 브레이크 포인터의 조건문에 아래와 같이 적을 수 있다 :

name[0] == 'k' && name[1] == 'u' && ... && name[4] == 't' && name[5] == 'a'

간단한 작업이긴 하지만 상당히 귀찮은 작업이기도 하다. 하지만 어쩌겠는가. 소스코드를 수정할 수도 없으니 저렇게 하지 않으면 값의 비교가 불가능 한것을..

그리고 더욱 귀찮은 것은 데이터 타입이 std::string 인 경우다. std::string의 경우에는 위와 같이 변수 이름을 통해 바로 해당 포인터로 접근 할 수가 없다. std::string 클래스 내부의 포인터 버퍼를 직접 가리켜 줘야 정상적인 비교가 된다. 예를 들어 :

std::string name = "kukuta";
std::cout << "name : " << name << std::endl; // 여기서 name이 "kukuta" 일때만 멈추고 싶음

위와 같은 코드에서 name의 내부 구조를 보면 아래와 같다 :


필자의 경우는 '((str)._Bx)._Buf' 와 같이 해당 포인터 변수에 접근 할 수 있었다. 그렇다면 조건식에는 어떻게 적어 줘야 할까? 아래와 같이 하면 된다.

((str)._Bx)._Buf[0] == 'k' && ... && ((str)._Bx)._Buf[5] == 'a'

더 복잡해 지지 않았는가? 제발 특정 문자열을 조건으로 삼아야 할 때는 소스 코드도 같이 수정 할 수 있기만을 기도하자.

참고적으로 Visual Studio 2010 버젼에서는 디버거에서 문자열 자체에 대한 condition breakpoint에 대한 지원도 한다고 합니다.


Reference :
 - http://www.developmentnow.com/g/51_2003_7_0_0_280475/Conditional-Breakpoint-not-hit--Need-some-help.htm : 하드한 문자 하나씩 비교 방법
 - http://www.suodenjoki.dk/us/archive/2010/conditional-breakpoint.htm : VS 2010 문자열 지원 뉴스

유익한 글이었다면 공감(❤) 버튼 꾹!! 추가 문의 사항은 댓글로!!