c++2013.07.04 11:41

C++표준 string (basic_string)을 printf 형식으로 사용하는 편한 방법이 없을까?  인터넷 찾아보면 여러가지 방법들이 나오긴하는데, static 변수를 이용하여 편하고/간결하고/오버헤드 없이 구현해 보았다. 


void strFormat(string &strResult, const char *pFormat, ... )

{

 static char sprintf_buffer[8192];


va_list va = NULL;

va_start(va, pFormat);

vsprintf(sprintf_buffer, pFormat, va);

strResult = sprintf_buffer;


va_end(va);

}


void strReplace(string& subject, const string& search, const string& replace)

{

size_t pos = 0;


while((pos = subject.find(search, pos)) != string::npos) {

subject.replace(pos, search.length(), replace);

pos += replace.length();

}

}


덤으로, strReplace는, string.find 와 string.replace의 조합을 이용하여 find&replace하는 함수인데 메모리할당을 하지 않고 비교적 빠른속도로 처리한다.


Posted by Jadumate

댓글을 달아 주세요

c++2013.07.03 21:46

개발환경 : C++/STL/Linux/gcc

프로그램을 짜다 보면 잘 못 짜서  어디선가 무한루프에 빠져서 헤어나질 못하는 경우가 종종 있는데, 이럴때 SIGALRM을 이용하여 이 녀석이 대체 무슨 짓을 하고 있었는지 자세하게 확인할 수 있다.

// signal handler

static void SigAlarm(int signo)

{

        ...

        closing_routine();

        ....

abort(); // exit with core_dump

}


int main(){

// 핸들러 설정

if(signal(SIGALRM, SigAlarm) == SIG_ERR) ERROR("signal ALARM error");

...

// main loop
while(1){

alarm(5); // 알람설정 5초

...

do_something();

...

alarm(0); // 알람 해제

}

}


SIGALRM에 대한 핸들러를 설정해두고, alarm(n)함수를 호출하면, n초후에 핸들러가 호출된다. 문제가 없을 경우 알람을 해제하고, 전체적으로 이 과정을 반복하도록 하였다. 

위 소스에서는 알람이 발생되면, 메인루프의 한 턴을 5초이상 쓰고 있다는 것인데, 이런 경우는 비정상적인 상황이라고 판단하여 코어 덤프하고 종료하도록 하였다. 나중에 gdb 를 이용하면 무슨짓을 하고 있었는지 상세하게 확인할 수 있다. 

앞서 포스트의 Call stack, Back trace글을 참고.


Posted by Jadumate

댓글을 달아 주세요

c++2013.07.03 21:37

누가 이 함수를 호출하였을까?


개발환경 : C++/STL/Linux/gcc

디버깅을 하다보면, 대체 어디서 이 함수를 호출했을까 궁금해질때가 있다.  이럴때 호출한 함수들을 역순으로 알아낼 수 있는 함수 루틴. 

#include <execinfo.h>

void call_stack_dump() {

void *   array[50];

char **  messages;

int      size, i;


size     = backtrace(array, 50);

messages = backtrace_symbols(array, size);


// skip first stack frame (points here)

for (i = 0; i < size; ++i){

fprintf(stderr, "[bt]: (%d) %s\n", i, messages[i]);

}


free(messages);

}


컴파일 할때에 -g -rdynamic 옵션을 주어야 한다. 이 방법 말고도 프로그램을 바로 죽여도 좋다면 더 쉬운 방법이 있다.


abort()를 이용하여 코어덤프하고 종료시키자

 #include <stdlib.h>

 void abort(void);


이렇게 하면 core 파일이 생기는데,  gdb를 이용하여 back trace하면 자세히 확인할 수 있다. 



core 파일을 이용하여 GDB로 Backtrace 하기


$ gdb chat4 core.2838

Core was generated by `/work/chat4 -D'.

Program terminated with signal 6, Aborted.

#0  0xffffe410 in __kernel_vsyscall ()

(gdb) bt

#0  0xffffe410 in __kernel_vsyscall ()

#1  0x00943df0 in raise () from /lib/libc.so.6

#2  0x00945701 in abort () from /lib/libc.so.6

#3  0x080579ed in SigAlarm (signo=14) at chat4.cc:3799

#4  <signal handler called>

#5  0x00982bbb in _int_free () from /lib/libc.so.6

#6  0x00983329 in free () from /lib/libc.so.6

#7  0xf7f50fe1 in operator delete(void*) () from /usr/lib/libstdc++.so.6

#8  0xf7f2dbad in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::_Rep::_M_destroy(std::allocator<char> const&) () from /usr/lib/libstdc++.so.6

#9  0xf7f30757 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() () from /usr/lib/libstdc++.so.6

#10 0x08065515 in __gnu_cxx::new_allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::destroy (this=0xfff3c417, __p=0x9e23750)

...


불특정한 순간에 무한루프에 빠지는 증상을 찾기 위해, SIGALRM을 설정하여, 알람이 발생한 경우 abort()를 호출하여 core dump 하도록 하였다. 이 경우는 string 을 free 하다가 미궁(?)에 빠진 것인데... 아직 정확한 원인은 못 찾고 있다. ㅠㅠ


Posted by Jadumate

댓글을 달아 주세요