잔머리는 삶의 지혜 : 위치로그 : 태그 : 방명록 : 관리자 : 새글쓰기
잔머리는 삶의 지혜 블로그에 오신것을 환영해요^^
시합은 이제 막 시작됐는걸, 아직 9번이나 공격할수 있다고.
71
73
34089

   
'Tip'에 해당되는 글 2건
XP에서 스레드를 사용하는 프로그램을 디버깅하다 보면 자주 OS가 멈춰버려서 리부팅까지 해야 되는 상황이 자주 발생합니다. 이 때문에 98이나 2000 에서 디버깅을 하기도 했는데 VC++ 6.0과 XP가 충돌하는 것으로도 의심을 했었지만 VC++2005 에서도 동일한 문제가 생긴다고 합니다.
그래서 검색을 해보니 원인은 IME 쪽 버그라고 합니다.
해결방법은 제어판 --> 국가 및 언어 옵션 --> 언어 탭 --> 자세히... --> 고급 --> 고급 텍스트 서비스 사용 안 함 을 체크하고 리부팅을 합니다.
2007/01/16 03:50 2007/01/16 03:50
How To Find Memory Leaks
Scrap, (2006/10/26 23:55)
How To Find Memory Leaks
by document.write(' Dion Picco (23 May 2000)



Introduction


I was recently working on a rather large project, the largest I had ever been involved with. We didn't have a concrete design document on this project so ideas and implementations were constantly changing. This is a great flexibility from a design/creation standpoint, but from a programming perspective it ended up becoming a rather large mess. Deep into the project we realized that with release date approaching we should tackle the task of cleaning up the garbage code and stabilizing it for alpha testing. Being a small company however meant that programs like BoundsChecker?from NuMega were just not within our reach. So we had to improvise. We needed a drop in solution to our current code base (the code base was entirely C++). We didn't want a project specific fix however. We needed a simple solution that could easily be compiled into this project and any other. Then at the end of runtime it would generate a list of the un-freed memory blocks. Well, of course we found it, otherwise this article would not be. We'll be right back after these messages to bring you the solution!

We're back. Let me elaborate more on exactly what we needed in our "memory tracer". We first needed something that could be added to any existing code base. Code reuse is a very important consideration, especially to a company. It can potentially save hundreds of hours and thousands of dollars. Secondly, our solution had to be simple. We didn't have time nor the courage to wade through thousands of lines of code doing re-writes and fixes to accommodate our memory tracer. And finally, it had to be free.

So we took a look at our code. The first thing we noticed is that nearly all of our memory allocations were accomplished through the operator new and variants. And likewise the de-allocations were accomplished through delete and variants. Well, we could replace all occurrences of new and delete with proprietary functions that tracked our memory for us? No! Too many replacements! C++ allows you to override new and delete in your classes. That would be great news if it didn't mean adding these overrides to all our classes. Wait a minute... I can override the global new and delete operators!!! Now I can do whatever just before each memory allocation and de-allocation! This great news! Sort of. I had actually known about this in a roundabout way. You see, MFC also has this ability. It is exploited through some of the _Crt() functions. Now that we have our back door, all we need to do is to track the allocations and cross-reference them with the de-allocations at destruction time. What doesn't get referenced is a leak. Simple.

Lets get to the workings of it shall we. All my work and references are written using Visual C++. It should be trivial to convert to other vendors. The first thing to do is to override new and delete so that they will be overridden everywhere in the program. In stdafx.h, I add:


     #ifdef _DEBUG
     inline void * __cdecl operator new(unsigned int size, 
                                        const char *file, int line)
     {
     };

     inline void __cdecl operator delete(void *p)
     {
     };
     #endif


These are my overridden functions. And by encasing them with #ifdef/#endif quotes, I don't get sub-par code with Release builds. When you look at the code you'll notice that new has been overridden with three parameters. These are the size of the requested allocation as well as the file and line from the source file where the allocation takes place. This is necessary in finding where the leaks are. Otherwise they would take a lot of assembly digging to find. By adding this however, all our code base that calls new() still refers to the operator new function that accepts one parameter, and not our three parameter new function. In addition, we wouldn't want to recode all our new operator statements to include the __FILE__ and __LINE__ arguments. What we need to do is to automatically make the one-parameter new operator call a three-parameter new operator call. This can be accomplished with some macro trickery.



     #ifdef _DEBUG
     #define DEBUG_NEW new(__FILE__, __LINE__)
     #else
     #define DEBUG_NEW new
     #endif
     #define new DEBUG_NEW



Now all of our one-parameter new operator calls are three parameter new calls with the __FILE__ and __LINE__ automatically inserted by the pre-compiler. Now is time for the actual tracking. We should also add the memory routines to our overridden functions so that they at least do what the old new/delete operator functions did.



     #ifdef _DEBUG
     inline void * __cdecl operator new(unsigned int size,
                                        const char *file, int line)
     {
          void *ptr = (void *)malloc(size);
          AddTrack((DWORD)ptr, size, file, line);
          return(ptr);
     };
     inline void __cdecl operator delete(void *p)
     {
          RemoveTrack((DWORD)p);
          free(p);
     };
     #endif



In addition to these, you may also need to override the new[] and delete[] operators as well. They are the same so I just left them out to save space.

Finally we need to supply some code the tracking functions AddTrack() and RemoveTrack(). I use the STL to maintain my linked list of allocations. You can use whatever. They two functions can contain any code you wish and then some. But I'll provide you with my version just in case you have coders block.


      
     typedef struct {
          DWORD address;
          DWORD size;
          char file[64];
          DWORD line;
     } ALLOC_INFO;

     typedef list<ALLOC_INFO*> AllocList;

     AllocList *allocList;

     void AddTrack(DWORD addr,  DWORD asize,  const char *fname, DWORD lnum)
     {
          ALLOC_INFO *info;

          if(!allocList) {
               allocList = new(AllocList);
          }

          info = new(ALLOC_INFO);
          info->address = addr;
          strncpy(info->file, fname, 63);
          info->line = lnum;
          info->size = asize;
          allocList->insert(allocList->begin(), info);
     };

     void RemoveTrack(DWORD addr)
     {
          AllocList::iterator i;

          if(!allocList)
               return;
          for(i = allocList->begin(); i != allocList->end(); i++)
          {
               if((*i)->address == addr)
               {
                    allocList->remove((*i));
                    break;
               }
          }
     };



Now, at the very last moment before our program exits, allocList is a list of all memory allocations that have not been freed. But in order to see what and where they are, you need to dump the information stored within allocList. I use the output window in Visual C++ for this. You can format this information in any way but what I've provided just dumps the list of information. Note that using the debug output window of Visual C++ may result in some lines of text not getting outputted before it cuts off.

      
     void DumpUnfreed()
     {
          AllocList::iterator i;
          DWORD totalSize = 0;
          char buf[1024];

          if(!allocList)
               return;

          for(i = allocList->begin(); i != allocList->end(); i++) {
               sprintf(buf, "%-50s:\t\tLINE %d,\t\tADDRESS %d\t%d unfreed\n",
               (*i)->file, (*i)->line, (*i)->address, (*i)->size);
               OutputDebugString(buf);
               totalSize += (*i)->size;
          }
          sprintf(buf, "-----------------------------------------------------------\n");
          OutputDebugString(buf);
          sprintf(buf, "Total Unfreed: %d bytes\n", totalSize);
          OutputDebugString(buf);
     };



There you have it. A bit of reusable code that you can use in all your projects to track all your memory leaks. I always add these functions to every project I start working on and I've used them to clean up projects already completed. It may not help make your game look the best, but it will hopefully help stabilize it. Take care everyone and send me any and all comments.
2006/10/26 23:55 2006/10/26 23:55
«   2009/01   »
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
어플에 폰트 임베드 하기.
대학원 등록금. (2)
썬더버드 인코딩 자동....
플의 생각.
ple's me2DAY 2008
유용한 util.
都心 속 道心 2007
세상에는 대단한 사람들이....
都心 속 道心 2007
WIPI/BREW 에서의 자체 폰....
바람에 흩날리는 달빛 2007
언제 다이어그램을 그려야....
너구리의 프로그래밍 세계 2007