home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / memleak.zip / MEMLEAKS.INF (.txt)
OS/2 Help File  |  1996-04-04  |  156KB  |  1,649 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. Authors ΓòÉΓòÉΓòÉ
  3.  
  4. Version 1.0 
  5.  
  6. Steve Hargis 
  7. Mike Skelton 
  8. IBM Corporation 
  9. Personal Software Products 
  10. LAN Systems Performance 
  11. Austin, Texas 
  12.  
  13. Please send comments to: 
  14.    Internet: hargis@vnet.ibm.com 
  15.    IBM Mail ID: usib4pvk@ibmmail 
  16.  
  17.  
  18. ΓòÉΓòÉΓòÉ 2. Trademarks ΓòÉΓòÉΓòÉ
  19.  
  20. References in this publication to IBM products, programs, or services do not 
  21. imply that IBM intends to make these available in all countries in which IBM 
  22. operates. Any reference to an IBM product, program, or service is not intended 
  23. to state or imply that only IBM's product, program, or service may be used. Any 
  24. functionally equivalent product, program, or service that does not infringe any 
  25. of IBM's intellectual property rights or other legally protectable rights may 
  26. be used instead of the IBM product, program, or service. Evaluation and 
  27. verification of operation in conjunction with other products, programs, or 
  28. services, except those expressly designated by IBM, are the user's 
  29. responsibility. 
  30.  
  31. IBM may have patents or pending patent applications covering subject matter in 
  32. this document. The furnishing of this document does not imply giving license to 
  33. these patents. Written license inquiries may be sent to the IBM Director of 
  34. Commercial Relations, IBM Corporation, Purchase, NY 10577. 
  35.  
  36. The following terms in this publication, are trademarks of the IBM Corporation 
  37. in the United States and/or other countries: 
  38.  
  39. IBM Corporation               C Set/2, C/C++ Tools, IBM, OS/2, SPM/2, Theseus2 
  40.  
  41.  
  42. ΓòÉΓòÉΓòÉ 3. Abstract ΓòÉΓòÉΓòÉ
  43.  
  44. This paper reviews memory leak detection and fixes as experienced by the IBM 
  45. LAN Systems Performance area using the IBM C Set/2, IBM C/C++ Tools, and other 
  46. compilers with Theseus2. The use of compiler facilities and utility programs to 
  47. detect and fix memory leaks are demonstrated. The paper also discusses why 
  48. memory leaks are a concern, what can be done to detect and fix them, and how to 
  49. avoid memory leak problems. We give extensive examples of how common memory 
  50. leaks are detected and fixed using the tools described in the paper. 
  51.  
  52. Software designers, developers, testers, performance analysts or others who are 
  53. responsible for producing memory neutral software will benefit from the design 
  54. and programming recommendations and tools described in this paper. It is our 
  55. hope that the techniques used in this paper will become part of the repertoire 
  56. of every developer and that the tools covered here will become part of the 
  57. toolbox of every analyst. 
  58.  
  59.  
  60. ΓòÉΓòÉΓòÉ 4. Introduction ΓòÉΓòÉΓòÉ
  61.  
  62. Creating an excellent software product includes two goals. First, is making the 
  63. product excellent through good design and development. Second, is iterating 
  64. through comprehensive testing until all problems are fixed. We will focus on 
  65. these goals as they pertain to memory management in software products. 
  66.  
  67. We cover the methodology and tools needed to be proactive/preventative in 
  68. getting memory management right during design, code and unit test. We also 
  69. address the methodology and tools needed to effectively react to memory 
  70. management bugs found in the integration and system test phases. 
  71.  
  72. It seems only fair that we disclose any bias that may occur as we write. This 
  73. white paper is written by members of a performance team; that is not to say 
  74. that some of us do not have any code in products, we do. It does indicate that 
  75. we highly value design and analysis before development in order to avoid errors 
  76. and more analysis during development and test. As we look at code we consider 
  77. its resource usage (i.e. CPU time, disk, memory, communication channels) and 
  78. effects on other applications that will run concurrently. Thus we value low 
  79. resource utilization over fast development and economy of resources over 
  80. easy-to-code solutions. It is our experience that adherence to disciplined 
  81. design and development will lead to increased software productivity and shorter 
  82. development and test cycles. 
  83.  
  84. Teachers are often told to teach by 1) telling the students what you are going 
  85. to teach them; 2) teach them; and 3) tell them what you taught them. Thus, 
  86. after some basic definitions (the first section), the paper lists the lessons 
  87. that we learned (the second section) about memory debugging as it relates to 
  88. product development. We try to be clear and explicit. The third section of the 
  89. paper lists the tools that we used and discusses how we used each tool; 
  90. hopefully, this will equip developers to apply the tools to software products. 
  91. The last section of the paper is several examples of exactly how we detected 
  92. and plugged different types of memory leaks. This last section can be viewed as 
  93. a tutorial. Two appendices are also included. The first appendix documents an 
  94. anomaly that causes memory leaks when C code is interfaced with C++ code. And 
  95. the second appendix is excerpted and edited forum questions and answers about 
  96. the memory management function malloc. 
  97.  
  98.  
  99. ΓòÉΓòÉΓòÉ 5. Definitions ΓòÉΓòÉΓòÉ
  100.  
  101. Memory Leak A memory leak is memory a program allocates or that is allocated on 
  102.      a program's behalf, that is not freed after the program is finished with 
  103.      it. If the same action is executed again, the program allocates more 
  104.      memory instead of using memory previously allocated. With repeated 
  105.      executions the program accumulates more memory than it needs. The 
  106.      accumulation of memory by the leaking program prevents other applications 
  107.      and system functions from using the memory, thereby interfering with the 
  108.      systems operation. 
  109.  
  110.      Memory leaks are usage dependent, like any programming bug. A program that 
  111.      has not leaked when running one set of test cases may leak when running a 
  112.      different test case. 
  113. Memory Overwrite Also called a memory walker. A memory overwrite occurs when a 
  114.      program allocates less memory than it actually writes to a location. The 
  115.      effect is to overwrite and possibly wipe out data that happens to be 
  116.      located immediately after it in memory. Whether or not a memory overwrite 
  117.      occurs depends on how many additional bytes are stored beyond the amount 
  118.      allocated. The observable symptom is intermittent data corruption, which 
  119.      is dependent upon the length of data stored in memory (which is not an 
  120.      intuitive item to check). How the length of data is related to memory 
  121.      overwrites is the subject of an example in Section Detection and Solution 
  122.      Examples. 
  123. Memory Neutrality A module, component, function, API, program, system, etc. is 
  124.      said to be memory neutral if it 
  125.  
  126.     1. deallocates all memory for which it is responsible (this is usually the 
  127.        same memory that it allocates, however some specification standards 
  128.        specify that function A is supposed to deallocate memory allocated by 
  129.        function B); and 
  130.  
  131.     2. does not attempt to deallocate more memory than that for which it is 
  132.        responsible. Both of these items must be true for memory neutrality. The 
  133.      basic definition is straight forward: Deallocate all, and only the memory 
  134.      that you allocate. However, when specifications call for different modules 
  135.      to delete memory than allocated the memory, the definition gets a little 
  136.      fuzzy in order to include such cases. The "memory than that for which it 
  137.      is responsible" wording takes care of unusual specifications. 
  138.  
  139.  
  140. ΓòÉΓòÉΓòÉ 6. Design and Programming Recommendations ΓòÉΓòÉΓòÉ
  141.  
  142. Our experiences have motivated creation of a set of design and programming 
  143. recommendations that focus specifically on memory management. Their purpose is 
  144. to be proactive during design, code, unit test and functional test so that 
  145. discovery of memory problems, in complex system tests, is limited to genuinely 
  146. complex problems that could not reasonably be found in simple test 
  147. environments. The earlier in the product development that these recommendations 
  148. are applied the smoother (and faster) development will go. 
  149.  
  150. Know the memory usage of each component within the product. 
  151.      A development approach that has gained much popularity is prototyping 
  152.      code. A quick prototype is used to prove that a concept will work, with 
  153.      the expectation that the lessons learned from the prototype will be kept 
  154.      but the prototype itself will be discarded and "real," quality code will 
  155.      be written for the product. However, schedules are often aggressively 
  156.      short and the prototype becomes the product. We have noticed that a major 
  157.      short cut taken in prototypes is in memory management. And why not? The 
  158.      prototype runs for a short time using whatever memory is needed and ends, 
  159.      thus freeing any memory used. As the accumulation of prototypes comes 
  160.      together as a product there has been neither a design for memory 
  161.      management nor a prototype for memory management. 
  162.  
  163.      It is difficult to diagnose memory problems when no one has the big 
  164.      picture of how the product is supposed to use memory. The logical person 
  165.      to know what is supposed to happen is the developer, but he may need 
  166.      assistance in discovering what is really happening. Diagnosing memory 
  167.      problems usually requires an analyst using special software tools to 
  168.      provide an "under the covers" look at program behavior AND the developer 
  169.      to provide knowledge about what is supposed to be happening. The analyst 
  170.      provides expertise on what is actually occurring and the developer 
  171.      provides expertise on what is supposed to be occurring. Together their 
  172.      expertise can be used to make the product behave as it was designed. 
  173.      Ideally, the analyst and the developer are the same person. 
  174.  
  175. Do not rely on the operating system to delete memory when the process dies. 
  176.      This is a common practice with, what would seem, no ill effects. After 
  177.      all, if you need the memory until the process dies, why not let the 
  178.      operating system get rid of it for you? That the operating system will 
  179.      deallocate resources when the process dies is true; however, counting on 
  180.      that only works for relatively short-lived processes. A short running 
  181.      utility can count on that, but major processes that stay up for days, 
  182.      weeks or months should not be implemented that way. There are four main 
  183.      reasons 24/7 (24 hours a day, 7 days a week) processes, and arguably even 
  184.      shorter lived processes, should not rely on the operating system to delete 
  185.      resources. 
  186.  
  187.      The first is that resource consumption will grow over time; if the time is 
  188.      short-lived and the resource consumption is small it may be OK, but if the 
  189.      time is long then the resources consumed will to begin reach the maximum 
  190.      of the machine. For example, if memory is allocated to store information 
  191.      until a process dies and the process does not die for 3 weeks, the 
  192.      information stored will consume a lot of memory. Consuming lots of memory 
  193.      will cause some memory somewhere (wherever it is used the least) to be 
  194.      swapped. It will not take very long for the swap file to be so large that 
  195.      it adversely affects the performance of everything that runs on the 
  196.      machine - all because memory usage was not tracked when allocations began 
  197.      so the memory could be freed or reused when previous use has ended. 
  198.  
  199.      The second reason is that code may be ported or expected to run on a 
  200.      different operating system/platform. The new platform may not clean up 
  201.      resources as nicely as OS/2. Or perhaps the other platform does clean up 
  202.      nicely, today; but it may not in the next release. 
  203.  
  204.      A third reason to not rely on the operating system to delete memory when a 
  205.      process dies is that the program's design may change. Code may be written 
  206.      to run in a process of it's own, however the process/thread model of 
  207.      products are subject to change. Code may be consolidated from several 
  208.      processes into a smaller number of longer lived processes in order to 
  209.      avoid process overhead and process creation, deletion overhead. Therefore, 
  210.      code that started out in a process of its own may be consolidated to run 
  211.      on a thread(s) of a process containing other threads. Resources like 
  212.      memory, semaphores, files etc., are owned by the process, not by the 
  213.      thread. So, when the code now terminates the thread, the process remains - 
  214.      along with all of the resources accumulated by the thread but never freed. 
  215.  
  216.      The last reason for not relying on the operating system to delete 
  217.      resources is that debugging is greatly complicated by it. We strongly 
  218.      advocate use of the C Set/2 and C/C++ debug memory functions; when using 
  219.      them we have noticed that many programs are not memory neutral at the 
  220.      instruction immediately prior to returning control to the operating 
  221.      system. So if we are trying to fix a memory leak we must first decipher 
  222.      through the "noise" of memory that is being leaked "on purpose" and memory 
  223.      that is being leaked accidentally. This as a major hindrance to debugging. 
  224.  
  225.      Let us close this piece of advice by saying that sound coding practices 
  226.      include allocating machine resources as needed, tracking those resources 
  227.      and deallocating them at the earliest reasonable time. Relying on the 
  228.      operating system to clean up a process' use of resources is dangerous in 
  229.      todays cross-platform code environment. 
  230.  
  231. Avoid designs where one module allocates memory and another module deallocates 
  232. the memory. 
  233.      Unless of course, the design specification comes from a standards 
  234.      institute and you have no control over it. This sort of design can lead to 
  235.      problems such as: 
  236.  
  237.     1. Poor communications between memory allocation and deallocation modules, 
  238.        or programmers will lead to memory leaks. 
  239.  
  240.     2. When more than one C runtime exists, each runtime will need APIs to free 
  241.        memory and run _heapmin. Then memory allocated by a module compiled with 
  242.        one runtime can be called, by a module compiled with another runtime, to 
  243.        deallocate the memory. (_heapmin is a C runtime function that attempts 
  244.        to return unused heap memory to the operating system. It is an expensive 
  245.        call, thus it should not be run frequently. The algorithm for when it 
  246.        successfully returns memory to the operating system is complex. We 
  247.        recommend running _heapmin after a significant amount of processing in 
  248.        memory has completed and a lull of activity in the system is expected; 
  249.        this way the time to execute _heapmin may go unnoticed by the system 
  250.        users.) 
  251.  
  252.     3. Very few people, if anyone, will really know who is allocating what, for 
  253.        what, and who can deallocate or reuse what, under what conditions; and 
  254.        communicating that to fellow team members will be extremely difficult, 
  255.        not to mention the difficulties in answering/debugging memory usage 
  256.        questions. 
  257.  
  258. Minimize the number of different compilers used in the product. 
  259.      Each compiler (and usually each version of a single compiler) has it own 
  260.      runtime library and runtime libraries do not communicate with each other. 
  261.      Inevitably, a module compiled with compiler x will want to know about 
  262.      memory structures compiled with compiler y. They will not be able to 
  263.      communicate unless you code that ability; that seems like a waste of good 
  264.      time. Multiple compilers will also complicate your build environment and 
  265.      your builds. 
  266.  
  267. Set the criteria for determining memory neutrality early in the development 
  268. cycle. 
  269.      Testing for memory neutrality can consume some time to create a build with 
  270.      memory debug features in it, execute test cases and analyze the data, but 
  271.      the results are worth the effort. If the memory usage is correct this 
  272.      analysis goes quickly. Our strong recommendation is that you use the debug 
  273.      memory features available in C Set/2 and C/C++ Tools in order to have an 
  274.      authoritative (the compiler knows best) source certify that your code is 
  275.      memory neutral. We recommend that memory neutrality be a test exit 
  276.      criteria beginning with functional verification test. If code has memory 
  277.      problems, finding and fixing them in a small environment is much easier 
  278.      than waiting until tests in a large, complex environment. Since memory use 
  279.      bugs are usage dependent, like any other code bug, some memory usage bugs 
  280.      may not show up until the code is used in a large, complex environment. 
  281.  
  282.  
  283. ΓòÉΓòÉΓòÉ 7. Memory Debugging Tools ΓòÉΓòÉΓòÉ
  284.  
  285. There are several tools that we have found to be very useful for debugging OS/2 
  286. memory problems. The sections that follow introduce the tools and their 
  287. features. We recommend that you become familiar with each of them. 
  288.  
  289.  
  290. ΓòÉΓòÉΓòÉ 7.1. C Set/2 and C/C++ Tools Debug Memory Management Features ΓòÉΓòÉΓòÉ
  291.  
  292. The C Set/2 and C/C++ Tools compilers have some invaluable features when it 
  293. comes to debugging memory problems. Most notable is their battery of debug 
  294. memory management features. This consists of debug versions of the calloc, 
  295. free, _heapmin, malloc and realloc functions. The debug versions, respectively, 
  296. are _debug_calloc, _debug_free, _debug_heapmin, _debug_malloc and 
  297. _debug_realloc; there is also a _dump_allocated function that prints 
  298. information about every object on the heap. Version 2 of the compiler also 
  299. supports debugging the new and delete operators. New and delete are C++ 
  300. operators/functions to allocate and deallocate memory; they are analogous to 
  301. malloc and free respectively (although some memory book keeping is added). 
  302. Using new eliminates the need for a call to sizeof and the need to cast the 
  303. returned pointer; likewise, using delete causes class destructors to be 
  304. automatically called. 
  305.  
  306. Note that although there are functions to debug tiled memory (see the C Library 
  307. Reference), there are no functions to debug DosAllocMem since that function is 
  308. not part of the compiler. 
  309.  
  310. The compiler can be told to use the debug versions of the memory management 
  311. functions instead of the regular versions at compile time. When you do this, 
  312. each memory function call automatically invokes _heap_check, which performs a 
  313. thorough check of the heap, its memory objects and all associated pointers. If 
  314. anything is out of order, processing is aborted and a diagnostic message is 
  315. output on stderr. At first it may be annoying that processing is aborted, but 
  316. it is helpful to know that memory was overwritten or that a bad pointer was 
  317. passed to a memory function. A bad or unrecognized pointer can result from 
  318. allocating memory with malloc and trying to free it with _debug_free, so do not 
  319. attempt to mix the regular and the debug versions of the memory functions. 
  320. Details about the C Set/2 and C/C++ Tools debug memory management functions can 
  321. be found in C Set/2 v1.00 User's Guide, chapter 13 and C/C++ Tools v2.00 C 
  322. Library Reference, pp.42-44 and under the specific function names. 
  323.  
  324. When a program aborts due to memory errors it is common for the compiler to 
  325. indicate that the error was before or after module xxx line yyy. An error 
  326. message like this indicates that an error was just detected; therefore, the 
  327. actual error occurred between the line referenced in the message and the last 
  328. memory function called (thus the last _heap_check performed). Finding the 
  329. memory function executed just prior to the one flagged is usually easy but can 
  330. be quite difficult in a multi-threaded environment. Section Detection and 
  331. Solution Examples gives detailed examples on how to solve the problems once 
  332. they are detected. 
  333.  
  334. Let's review the advantages of learning to use and using this tool. Then we 
  335. will cover how to use the debug versions of the memory management functions for 
  336. versions 1 and 2 of the compiler. 
  337.  
  338.  
  339. ΓòÉΓòÉΓòÉ 7.1.1. Benefits ΓòÉΓòÉΓòÉ
  340.  
  341.  1. The compiler is the definitive source as to whether or not a module has 
  342.     memory leaks. A home grown memory check scheme may suffer from the same 
  343.     blind spots as the code it was intended to check. We know of no better way 
  344.     to ensure that the C Set/2 and C/C++ Tools memory management functions are 
  345.     used in a memory neutral way than to use the __DEBUG_ALLOC__ flag and its 
  346.     features. 
  347.  
  348.  2. Some memory errors are detected only when the memory debug functions are 
  349.     turned on (i.e. passing a bad pointer to free and memory overwrites). 
  350.  
  351.  3. It is not hard to use; although some code additions may be required for C++ 
  352.     code that redefine/overload the new and delete operators. 
  353.  
  354.  
  355. ΓòÉΓòÉΓòÉ 7.1.2. Turning them on for C Set/2 v1 ΓòÉΓòÉΓòÉ
  356.  
  357.  1. Include stdlib.h in each module (or in each module that uses the memory 
  358.     functions if you want to take the time to determine which ones those are). 
  359.  
  360.  2. On all compilations add the __DEBUG_ALLOC__ flag (i.e. /D__DEBUG_ALLOC__). 
  361.     We suggest making the __DEBUG_ALLOC__ flag, and/or compile flags, an 
  362.     environment variable in the build process. This allows uniform control over 
  363.     the build. Mixing normal and debug memory management functions should not 
  364.     be a problem. The _heap_check and _dump_allocated functions only work with 
  365.     memory allocated by the debug memory management functions. 
  366.  
  367.  3. Locate the point in your code where you return control to the operating 
  368.     system (your code should be memory neutral at this point). Just prior to 
  369.     this point add a call to the _dump_allocated(16) function that is 
  370.     conditional based on the flag discussed in step 2 above. For example: 
  371.  
  372.         #ifdef __DEBUG_ALLOC__
  373.            _dump_allocated(16);
  374.         #endif
  375.  
  376.     It can also be useful to use dump_allocated before and after a memory 
  377.     neutral function, operation or test case is executed to determine if the 
  378.     function, operation or test case is actually memory neutral. 
  379.  
  380.  4. Recompile and relink your code. Run a test case. 
  381.  
  382.  
  383. ΓòÉΓòÉΓòÉ 7.1.3. Turn them on for C/C++ Tools v2 ΓòÉΓòÉΓòÉ
  384.  
  385.  1. Include stdlib.h in each module (or in each module that uses the memory 
  386.     functions if you want to take the time to determine which ones those are). 
  387.  
  388.  2. On all compilations add the /Tm+ option (which implicitly defines a macro 
  389.     called __DEBUG_ALLOC__). We suggest making the __DEBUG_ALLOC__ flag, and/or 
  390.     compile flags, an environment variable in the build process. This allows 
  391.     uniform control over the build. Mixing normal and debug memory management 
  392.     functions should not be a problem. The _heap_check and _dump_allocated 
  393.     functions only work with memory allocated by the debug memory management 
  394.     functions. 
  395.  
  396.  3. Every place that your code redefines (not calls) the new or delete 
  397.     operators you must conditionally compile based on the flag/macro discussed 
  398.     in step 2 above. When the __DEBUG_ALLOC__ macro is defined, use of new or 
  399.     delete must include room for 2 additional parameters and they must be the 
  400.     second and third parameters. The examples below indicate what the calls 
  401.     should look like; these modifications have been tested on simple and 
  402.     complex usage of the new and delete operators. Complex uses include 
  403.     redefining the operators for an inherited class and overriding/adding 
  404.     parameters to the new operator (this cannot be done with the delete 
  405.     operator). 
  406.  
  407.         #ifdef __DEBUG_ALLOC__
  408.  
  409.         void* operator new(size_t size, const char *, size_t)
  410.         {
  411.            void* pTemp;
  412.            APIRET SubAllocRC = SH.SubAlloc(size, &pTemp);
  413.            if (SubAllocRC)
  414.            {
  415.              cout << "shared::operator new:  ";
  416.              cout << "SH.SubAlloc error:  " << SubAllocRC << endl;
  417.              return NULL;
  418.            }
  419.            return (pTemp);
  420.         }
  421.  
  422.         void  operator delete(void* pDel, const char *, size_t, size_t size)
  423.         {
  424.            APIRET SubFreeRC = SH.SubFree(pDel);
  425.            if (SubFreeRC)
  426.            {
  427.              cout << "shared::operator delete:  ";
  428.              cout << "heap.SubFree error:  " << SubFreeRC << endl;
  429.            }
  430.         }
  431.  
  432.         #else
  433.  
  434.         void* operator new(size_t size)
  435.         {
  436.           void* pTemp;
  437.           APIRET SubAllocRC = SH.SubAlloc(size, &pTemp);
  438.           if (SubAllocRC)
  439.           {
  440.             cout << "shared::operator new:  ";
  441.             cout << "SH.SubAlloc error:  " << SubAllocRC << endl;
  442.             return NULL;
  443.           }
  444.           return (pTemp);
  445.         }
  446.  
  447.         void  operator delete(void* pDel, size_t size)
  448.         {
  449.           APIRET SubFreeRC = SH.SubFree(pDel);
  450.           if (SubFreeRC)
  451.           {
  452.             cout << "shared::operator delete:  ";
  453.             cout << "heap.SubFree error:  " << SubFreeRC << endl;
  454.           }
  455.         }
  456.  
  457.         #endif
  458.  
  459.     Note in this example that new is redefined to use SH.SubAlloc, which is a 
  460.     class for using DosSubAllocMem, and delete is redefined to use SH.SubFree, 
  461.     which is a class for using DosSubFreeMem. Note also that when the 
  462.     __DEBUG_ALLOC__ macro is defined that new and delete have 2 additional 
  463.     parameters, 1 of type const char* and 1 of type size_t; the second and 
  464.     third parameters respectfully. 
  465.  
  466.  4. Locate the point in your code where you return control to the operating 
  467.     system (your code should be memory neutral at this point); just prior to 
  468.     this point add a call to the _dump_allocated(16) function that is 
  469.     conditional based on the flag discussed in step 2 above. For example: 
  470.  
  471.         #ifdef __DEBUG_ALLOC__
  472.            _dump_allocated(16);
  473.         #endif
  474.  
  475.     It can also be useful to use dump_allocated before and after a memory 
  476.     neutral function, operation or test case is executed to determine if the 
  477.     function, operation or test case is actually memory neutral. 
  478.  
  479.  5. Recompile and relink your code. Run your test cases. 
  480.  
  481.  
  482. ΓòÉΓòÉΓòÉ 7.1.4. Memory Debug Output and Analysis ΓòÉΓòÉΓòÉ
  483.  
  484. After compiling with the memory debug options turned on, your programs may 
  485. behave differently. They will definitely run slower, approximately double 
  486. previous run times. Each malloc, etc. will actually be calling _debug_malloc, 
  487. etc. plus a function called _heap_check. _heap_check runs through the heap and 
  488. validates all entries; if you pass an invalid pointer to free (which is truly 
  489. _debug_free now), _heap_check will print a message to that effect on stderr 
  490. (file handle 2) and cause the process to stop running. Thus all pointers to 
  491. free must be valid before the programs will run to completion; this has been 
  492. used to find messed up pointers and DosSubAllocMem pointers sent to free. 
  493.  
  494. When the heap is in a good state you should be able to run a test case and then 
  495. shutdown your component. Just before control is returned to the OS, the 
  496. _dump_allocated call will print information about heap storage that is still 
  497. allocated. Ideally it will say that your programs have no storage allocated; if 
  498. you do have storage allocated then you have a memory leak! The report is sent 
  499. to stderr (file handle 2) and includes the line number and name of the module 
  500. which allocated the memory, the pointer that points to the memory, how much 
  501. memory was allocated, and the first 16 bytes of that memory location (the 
  502. parameter 16 can be changed to as much or as little as is helpful to you). This 
  503. will tell you exactly where your memory leak is. 
  504.  
  505. The memory shown by the _dump_allocated located before the return to the 
  506. operating system will be freed by the operating system when the process is 
  507. terminated. A common response from developers is "Hey, all this memory will go 
  508. away when the process dies so I don't have to free it." Two points need to be 
  509. recalled here. First, if the memory shown by _dump _allocated gets larger the 
  510. longer the program has run, or gets larger depending on the operations the 
  511. program executed then, there is a problem to be fixed. Second, the 
  512. process/thread model of the product may change so that this code is no longer 
  513. in a process that terminates frequently to clean up behind the code. You also 
  514. will have to decide which memory from the _dump_allocated report was leaked on 
  515. purpose (because you decided to let the operating system clean up after your 
  516. process dies) and which was accidental - good luck. 
  517.  
  518. Your analysis can be greatly aided by the knowledge contained in appendix Forum 
  519. Q & A about Malloc and by the help screens of the next tool, Theseus2. 
  520.  
  521.  
  522. ΓòÉΓòÉΓòÉ 7.2. Theseus2 ΓòÉΓòÉΓòÉ
  523.  
  524. Theseus (pronounced Thee'-see-us) was one of the Attic heroes of Greek 
  525. mythology. According to legend, he was one of the young Greeks chosen to be 
  526. sacrificed to the Minotaur, the mythical half man/half bull confined in the 
  527. Labyrinth. Instead, Theseus killed the Minotaur. One of the local girls, 
  528. Ariadne, gave him a thread, which he used to mark his trail into and out of the 
  529. Labyrinth. He then married Ariadne and they sailed off into the sunset. 
  530.  
  531. The analogy of the labyrinth is appropriate, because assigning memory to a user 
  532. in the OS/2 environment is quite complex, much like the Labyrinth of old. 
  533. However, this program knows its way through the labyrinth and can assist you in 
  534. determining the amount of memory used by your program. No tool gives such a 
  535. complete view and analysis of what is occurring with OS/2 memory management. It 
  536. is commercially available as part of the SPM/2 (System Performance Product/2) 
  537. product, internal users can get it from the OS2TOOLS disk. Its device driver 
  538. gives it access to memory structures that lesser programs would fear to grapple 
  539. with. 
  540.  
  541. OS/2 memory experts have spent years putting their expertise into this program. 
  542. It analyzes memory as well as the swapper.dat file, giving access to all 
  543. contents. It contains a memory leak detector, for private and shared memory, 
  544. along with formatted, hyper-linked displays of the virtual, linear, physical 
  545. and module views of memory. Monitoring or reporting can be done at the system 
  546. level or on a per process basis. This is one slick tool that opens up the world 
  547. of OS/2 memory management as far as you care to go. The uninitiated (to OS/2 
  548. memory management) can get very useful information from Theseus2 and the 
  549. experts who created the tool routinely use it to debug. Its memory leak 
  550. detector will detect leaks long before monitoring the swapper.dat file would 
  551. indicate, and it will indicate who is leaking. 
  552.  
  553.  
  554. ΓòÉΓòÉΓòÉ 7.2.1. Theseus2 Memory Utilization ΓòÉΓòÉΓòÉ
  555.  
  556. Knowing how processes in OS/2 are using memory is very helpful in determining 
  557. which program is leaking. Let us repeat again that Theseus2 is a very 
  558. comprehensive tool, what we demonstrate here is very limited. Theseus2 can show 
  559. how much memory is used (private and shared, allocated, committed and present 
  560. within private and shared). Taking a baseline system measurement, running a 
  561. program that leaks and taking a second measurement, indicates which process 
  562. grew and might be leaking - it is surely a good place to look at more closely. 
  563. Below is an example of Theseus2 output for both system and process level memory 
  564. utilization at a point in time. If some of the terminology is foreign don't 
  565. worry, Theseus2 has context sensitive helps including an "Explanation of the 
  566. contents of this window" for every screen. Below is the initial screen and the 
  567. System menu. 
  568.  
  569. Theseus2 main screen 
  570.  
  571.  
  572. ΓòÉΓòÉΓòÉ 7.2.1.1. At the System Level ΓòÉΓòÉΓòÉ
  573.  
  574. If the option above, where the arrow is pointing, is chosen then output 
  575. formatted like the example below would result. The System, RAM Usage by Process 
  576. report reports which executable (.exe or .dll) owns how much private and shared 
  577. memory. The last column on the right-hand side labeled "who" is the internal 
  578. name of the executable. The internal name is the same as the external or file 
  579. name for DLLs, but that is not necessarily true for .exe files. The division of 
  580. private and shared memory is clearly labeled; the "bytes", "Kbytes" and 
  581. "Mbytes" labels are the same information in three different formats. 
  582.  
  583. RAM Usage by Process:
  584. --------- private --------   ------ owned shared ------
  585.    bytes   Kbytes   Mbytes      bytes   Kbytes   Mbytes   who
  586. 008C9000     8996    8.785   001D3000     1868    1.824   system
  587. 00000000        0    0.000                                sysinit
  588. 00000000        0    0.000                                IP2IDMN
  589. 00000000        0    0.000                                LANDLL
  590. 00000000        0    0.000                                LANMSGEX
  591. 00006000       24    0.023                                CNTRL
  592. 00002000        8    0.008   00002000        8    0.008   SPMNBL
  593. 00000000        0    0.000                                LSDAEMON
  594. 00002000        8    0.008                                LOGDAEM
  595. 00000000        0    0.000                                EPWROUT
  596. 00017000       92    0.090   00112000     1096    1.070   PMSHL32
  597. 00000000        0    0.000                                EPWRES
  598. 00002000        8    0.008                                SPMSNAPL
  599. 00000000        0    0.000   00015000       84    0.082   SPMNET
  600. 00000000        0    0.000                                HARDERR
  601. 00000000        0    0.000   00002000        8    0.008   STOPLAN
  602. 00054000      336    0.328   0001F000      124    0.121   PMSHL32
  603. 00006000       24    0.023   00004000       16    0.016   LEXAES
  604. 0000F000       60    0.059   0000C000       48    0.047   WKSTA
  605. 0000D000       52    0.051   00005000       20    0.020   CMKFMSMI
  606. 00000000        0    0.000                                MUGLRQST
  607. 00000000        0    0.000                                WKSTAHLP
  608. 00000000        0    0.000                                CMD
  609. 00000000        0    0.000                                LSCLIENT
  610. 00001000        4    0.004                                MSRV
  611. 00000000        0    0.000                                NETPOPUP
  612. 00000000        0    0.000   00043000      268    0.262   NETPSINI
  613. 0000C000       48    0.047   00004000       16    0.016   NETPSERV
  614. 00004000       16    0.016                                NETPSERV
  615. 00007000       28    0.027   00004000       16    0.016   NBQRSPND
  616. 00000000        0    0.000                                CMD
  617. 00000000        0    0.000                                CMD
  618. 00009000       36    0.035   00003000       12    0.012   CMD
  619. 0000C000       48    0.047                                VDM
  620. 00059000      356    0.348   00004000       16    0.016   E
  621. 00000000        0    0.000                                CLIPAPI
  622. 0005F000      380    0.371   00009000       36    0.035   THESEUS2
  623. 00008000       32    0.031   00004000       16    0.016   CMVCPM
  624. 00000000        0    0.000                                LPD
  625. 00009000       36    0.035   0000F000       60    0.059   PORTMAP
  626. 0000E000       56    0.055                                NFSD
  627. 00000000        0    0.000                                CMD
  628. 00000000        0    0.000                                NFSCTL
  629. 00000000        0    0.000                                NFSBIOD
  630. 00000000        0    0.000                                NFSBIOD
  631. 00000000        0    0.000                                NFSBIOD
  632. 00000000        0    0.000                                NFSBIOD
  633. 00000000        0    0.000                                CMD
  634. 00000000        0    0.000                                CMD
  635. 00000000        0    0.000                                DMCM
  636. 00001000        4    0.004   00017000       92    0.090   RMMINTRM
  637. 00003000       12    0.012   0002C000      176    0.172   ASP000
  638. 00019000      100    0.098   0001D000      116    0.113   PCPRINT
  639. 00028000      160    0.156   0005E000      376    0.367   ACS3EINI
  640. 00021000      132    0.129   00006000       24    0.023   CMD
  641. 0002C000      176    0.172   00006000       24    0.023   MEMLEAKS
  642. --------   ------   ------   --------   ------   ------
  643. 00AF8000    11232   10.969   0046A000     4520    4.414   total RAM in use
  644. 0003E000      248    0.242   free RAM
  645. --------   ------   ------
  646. 00FA0000    16000   15.625   total of all RAM pages found (Pvt + Shr + Free)
  647. < End of THESEUS2 (v 2.0.1c) output @ 11:05:31 on 1-21-1994 >
  648.  
  649.  
  650. ΓòÉΓòÉΓòÉ 7.2.1.2. At the Process Level ΓòÉΓòÉΓòÉ
  651.  
  652. Memory Utilization for Process with PID = 00AB, name = 'MEMLEAKS':
  653.     bytes      bytes    number  bytes      bytes
  654. allocated  committed   present   each    present  description
  655.  00000824   00000824         1   0824   00000824  PTDA
  656.  000001AC   000001AC         1   01AC   000001AC  TCB
  657.  00001000   00001000         1   1000   00001000  TSD
  658.  00010000   00005000         5   1000   00005000  LDT
  659.  00000200   00000200         1   0200   00000200  Process Page Directory
  660.  00080000   00013000        19   1000   00013000  Page Tables
  661.  02D30000   007A8000       644   1000   00284000  Accessible Shared memory
  662.  00840000   00009000         6   1000   00006000  Originated Shared memory
  663.  00120000   00057000        44   1000   0002C000  Private memory
  664.  --------   --------                    --------
  665.  00091BD0   00019BD0                    00019BD0  Total System
  666.  00840000   00009000                    00006000  Total Shared originated
  667.  00120000   00057000                    0002C000  Total Private
  668.  --------   --------                    --------
  669.  009F1BD0   00079BD0                    0004BBD0  Total RAM for the Process
  670.     10183        487                         303  (in Kbytes)
  671.     9.945      0.476                       0.296  (in Mbytes)
  672.  
  673. The following values are taken directly from the PTDA:
  674. Allocated PTEs: private = 00057, shared = 007B8, total = 0080F.
  675. Present   PTEs: private = 0002C, shared = 00294, total = 002C0.
  676. Resident  PTEs: private = 00000, shared = 00010, total = 00010.
  677. < End of THESEUS2 (v 2.0.1c) output @ 11:05:44 on 1-21-1994 >
  678.  
  679.  
  680. ΓòÉΓòÉΓòÉ 7.2.2. Theseus2 Object Summary ΓòÉΓòÉΓòÉ
  681.  
  682. Another helpful report that is very fast when checking for memory leaks in a 
  683. specific process is the Private and Shared Object Summary. Often this affords a 
  684. quick look at a process that is supposed to use memory during processing and 
  685. free it all when processing is done. It lists each memory object belonging to 
  686. the process and, since the memory addresses on the screen are hyper-linked, it 
  687. is easy to quickly choose a memory that is new or has grown in committed size 
  688. (since a base measurement) and examine its contents. This is often a first step 
  689. in fixing a leak; if the developer recognizes the data structures in the object 
  690. that appears to be leaked then he may know where in the program to look. 
  691. Depending on the contents of the memory object you may discover that it is a 
  692. particular configuration file read into memory during initialization, a 
  693. recognizable data structure, or a set of linked lists x bytes in length. Each 
  694. piece of knowledge gained should narrow the search in the code for where the 
  695. leak originated. 
  696.  
  697. Below is example output of the Private Object Summary of Theseus2; it was 
  698. captured by single clicking on the process name in the main window of Theseus2, 
  699. then choosing the Process option from the main menu, and clicking on the 
  700. Private Object Summary option. Note that name of the executable in the column 
  701. labeled "Description" is 
  702.  
  703. MEMLEAKS
  704. .Thisisthenameofourexecutable ,notalabelthatTheseus2usestoindicateleaks 
  705. .Youwillhavetoanalyzetheinformationtodetermineifamemoryleakispresent 
  706. ,Theseus2merelyprovidestheinformation .
  707.  
  708. Private Object Summary for 'MEMLEAKS':
  709.   Object Allocated Committed   Present   Swapped
  710.  address    memory    memory    memory    memory  Description
  711. 00010000  00010000  0000A000  0000A000  00000000  MEMLEAKS #0001 (shared code)
  712. 00020000  00010000  0000A000  00003000  00000000  MEMLEAKS #0002 (private)
  713. 00030000  00010000  00001000  00001000  00000000  User Environment (hmte)
  714. 00040000  00010000  00001000  00001000  00000000  Thread Information Block (hmte)
  715. 00050000  00010000  00004000  00002000  00000000  stack (hmte [system owner])
  716. 00060000  00010000  00001000  00000000  00000000  MEMLEAKS allocated it
  717. 00070000  00010000  00010000  00005000  00000000  MEMLEAKS allocated it
  718. 00080000  00010000  00001000  00000000  00000000  MEMLEAKS allocated it
  719. 00090000  00010000  00002000  00001000  00000000  MEMLEAKS allocated it
  720. 000A0000  00010000  00001000  00001000  00000000  MEMLEAKS allocated it
  721. 000B0000  00010000  00002000  00001000  00000000  MEMLEAKS allocated it
  722. 000C0000  00010000  00001000  00000000  00000000  MEMLEAKS allocated it
  723. 000D0000  00010000  00002000  00000000  00000000  MEMLEAKS allocated it
  724. 000E0000  00010000  00010000  00010000  00000000  MEMLEAKS allocated it
  725. 00100000  00010000  00001000  00001000  00000000  PMWIN    allocated it
  726. 00110000  00010000  00001000  00001000  00000000  PMGRE    allocated it
  727. 00120000  00010000  00010000  00001000  00000000  PMGRE    allocated it
  728. 00130000  00010000  00001000  00000000  00000000  DISPLAY  #0000 (private)
  729.           --------  --------  --------  --------
  730. Totals:   00120000  00057000  0002C000  00000000  (in bytes)
  731.               1152       348       176         0  (in Kbytes)
  732.              1.125     0.340     0.172     0.000  (in Mbytes)
  733. Number of objects = 18.
  734. < End of THESEUS2 (v 2.0.1c) output @ 15:17:09 on 1-21-1994 >
  735.  
  736. By double clicking on one of the highlighted (indicating a hyper-link) 
  737. pointers, the contents of the field located at that pointer is brought up. We 
  738. choose the memory object at 00080000; note that its description above (EXE or 
  739. internal DLL name) is MEMLEAKS. Thus we know that the program allocated this 
  740. memory itself; if the program were dynamically linked it may well include 
  741. objects allocated from the C runtime DLL. This memory object contains what was 
  742. entered from the command line in response to a question posed by a test 
  743. program; it should not be too hard to guess what number we entered in response 
  744. to the question. 
  745.  
  746. Memory from Linear address 00080000 for 100 bytes for process 'MEMLEAKS':
  747. 00080000 (0000)  31 0A 00 00 00 00 00 00  00 00 00 00 00 00 00 00 *1...............*
  748. 00080010 (0010)  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 *................*
  749. 00080020 (0020)  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 *................*
  750. 00080030 (0030)  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 *................*
  751. 00080040 (0040)  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 *................*
  752. 00080050 (0050)  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 *................*
  753. 00080060 (0060)  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 *................*
  754. 00080070 (0070)  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 *................*
  755. 00080080 (0080)  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 *................*
  756. 00080090 (0090)  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 *................*
  757. 000800A0 (00A0)  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 *................*
  758. 000800B0 (00B0)  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 *................*
  759. 000800C0 (00C0)  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 *................*
  760. 000800D0 (00D0)  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 *................*
  761. 000800E0 (00E0)  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 *................*
  762. 000800F0 (00F0)  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 *................*
  763. < End of THESEUS2 (v 2.0.1c) output @ 15:25:47 on 1-21-1994 >
  764.  
  765.  
  766. ΓòÉΓòÉΓòÉ 7.2.3. Theseus2 Memory Leak Detection ΓòÉΓòÉΓòÉ
  767.  
  768. The last scratch which we will make into Theseus2 capabilities is to note the 
  769. memory leak detection option. We hope our reasons for covering it are obvious; 
  770. it was designed to indicate memory leaks before the mortal analyst could ever 
  771. catch it. Theseus provides a leak detector at both the system level and at the 
  772. process level. The system level leak detector gives reports about processes in 
  773. the system. The process level leak detector reports on memory object within 
  774. individual process. A useful approach in applying this pair of leak detectors 
  775. is as follows. First use the system leak detector to identify the leaking 
  776. process or processes. Then apply the process level leak detector to identify 
  777. what memory objects are leaking or what memory objects are being leaked. 
  778. Finally apply some code level analysis to identify why the memory object(s) is 
  779. leaking. Code level analysis identified in this paper are the Theseus2 memory 
  780. objects leak detection and C/C++ debug memory management functions. 
  781.  
  782. Consider this output from a sample program. It is being monitored by the memory 
  783. leak detection function at a system wide level. It reports changes in memory 
  784. activity every 15 seconds. Note that nothing occurred in the system until 
  785. 15:54:03 when a module named T2SAMP allocated and committed some memory in the 
  786. preceding 15 second period. T2SAMP then deallocated the same amount of memory 
  787. at 15:54:18 and allocated more memory at 15:54:33. After that nothing else 
  788. happened until the memory leak detector was stopped. 
  789.  
  790. Memory leak detection:
  791. < End of THESEUS2 (v 2.0.1c) output @ 15:52:51 on 1-21-1994 >
  792. Use the 'Function' pull-down to start and stop the data collection.
  793. Leak data captured.
  794. Previous sample will be used as the base.
  795. Periodic update started with interval of 0:15.
  796. < End of THESEUS2 (v 2.0.1c) output @ 15:53:25 on 1-21-1994 >
  797. < End of THESEUS2 (v 2.0.1c) output @ 15:53:48 on 1-21-1994 >
  798. ----------Private-----------  -----------Shared-----------
  799. Allocated  Committed  Actual  Allocated  Committed  Actual   PID   Name
  800.       +80         +5      +0                    +0      +0  00E1   T2SAMP
  801. < End of THESEUS2 (v 2.0.1c) output @ 15:54:03 on 1-21-1994 >
  802. ----------Private-----------  -----------Shared-----------
  803. Allocated  Committed  Actual  Allocated  Committed  Actual   PID   Name
  804.       -80         -5      +0                    +0      +0  00E1   T2SAMP
  805. < End of THESEUS2 (v 2.0.1c) output @ 15:54:18 on 1-21-1994 >
  806. ----------Private-----------  -----------Shared-----------
  807. Allocated  Committed  Actual  Allocated  Committed  Actual   PID   Name
  808.       +80         +5      +0                    +0      +0  00E1   T2SAMP
  809. < End of THESEUS2 (v 2.0.1c) output @ 15:54:33 on 1-21-1994 >
  810. < End of THESEUS2 (v 2.0.1c) output @ 15:54:48 on 1-21-1994 >
  811. < End of THESEUS2 (v 2.0.1c) output @ 15:55:03 on 1-21-1994 >
  812. < End of THESEUS2 (v 2.0.1c) output @ 15:55:18 on 1-21-1994 >
  813. Periodic update stopped.
  814. < End of THESEUS2 (v 2.0.1c) output @ 15:55:20 on 1-21-1994 >
  815.  
  816. This is a simplified example, with only 1 process doing anything in the system, 
  817. but it does clarify how to spot a module that has memory activity. The output 
  818. below is the same module being monitored at a process level. 
  819.  
  820. Memory leak detection for Process with PID = 00E2, name = T2SAMP:
  821. < End of THESEUS2 (v 2.0.1c) output @ 15:56:00 on 1-21-1994 >
  822. Use the 'Function' pull-down to start and stop the data collection.
  823. Leak data captured.
  824. Previous sample will be used as the base.
  825. Periodic update started with interval of 0:15.
  826. < End of THESEUS2 (v 2.0.1c) output @ 15:56:18 on 1-21-1994 >
  827. < End of THESEUS2 (v 2.0.1c) output @ 15:56:35 on 1-21-1994 >
  828. Allocated   Committed   Actual    har     Address   P/S   Description
  829.       +16          +1       +0   0C32   +00060000   Pvt   T2SAMP   allocated it
  830.       +16          +1       +0   0B65   +000B0000   Pvt   T2SAMP   allocated it
  831.       +16          +1       +0   0B6C   +000D0000   Pvt   T2SAMP   allocated it
  832.       +16          +1       +0   0C72   +000E0000   Pvt   T2SAMP   allocated it
  833.       +16          +1       +0   0BAD   +000F0000   Pvt   T2SAMP   allocated it
  834. < End of THESEUS2 (v 2.0.1c) output @ 15:56:50 on 1-21-1994 >
  835. Allocated   Committed   Actual    har     Address   P/S   Description
  836.       -16          -1       +0   0C32   -00060000   Pvt
  837.       -16          -1       +0   0B65   -000B0000   Pvt
  838.       -16          -1       +0   0B6C   -000D0000   Pvt
  839.       -16          -1       +0   0C72   -000E0000   Pvt
  840.       -16          -1       +0   0BAD   -000F0000   Pvt
  841. < End of THESEUS2 (v 2.0.1c) output @ 15:57:05 on 1-21-1994 >
  842. Allocated   Committed   Actual    har     Address   P/S   Description
  843.       +16          +1       +0   0BAD   +00060000   Pvt   T2SAMP   allocated it
  844.       +16          +1       +0   0C72   +000B0000   Pvt   T2SAMP   allocated it
  845.       +16          +1       +0   0B6C   +000D0000   Pvt   T2SAMP   allocated it
  846.       +16          +1       +0   0B65   +000E0000   Pvt   T2SAMP   allocated it
  847.       +16          +1       +0   0C32   +000F0000   Pvt   T2SAMP   allocated it
  848. < End of THESEUS2 (v 2.0.1c) output @ 15:57:20 on 1-21-1994 >
  849. < End of THESEUS2 (v 2.0.1c) output @ 15:57:35 on 1-21-1994 >
  850. Periodic update stopped.
  851. < End of THESEUS2 (v 2.0.1c) output @ 15:57:45 on 1-21-1994 >
  852.  
  853. Note that the +80 from the system level is seen on the process level as 5, 
  854. +16's. The +5 at the system level is seen as 5, +1's. Note also that even 
  855. though the description is missing when the memory was deallocated, the address 
  856. and har allow us to know that the memory belonged to T2SAMP. 
  857.  
  858. It will take the developer of T2SAMP to know whether this behavior is normal or 
  859. abnormal. If it is abnormal then this output, along with knowledge of what test 
  860. case was being run, we can begin to work with the developer to account for the 
  861. modules behavior and fix it if we determine that the behavior is not what was 
  862. intended. 
  863.  
  864.  
  865. ΓòÉΓòÉΓòÉ 7.2.3.1. At the Object Level ΓòÉΓòÉΓòÉ
  866.  
  867. A single click on any linear address in Theseus2 activates the "Memory Object 
  868. Leak Detection" option of the "Functions" menu at the top of the window. 
  869. Choosing this function will bring up a "Memory Leak Detection for <Linear 
  870. Address>" screen. Once we have determined that a memory leak exists (via system 
  871. memory leak detection) and we know which process is leaking (via process memory 
  872. leak detection), we can use the object memory leak detection facility. Often 
  873. the memory object is small enough that developers recognize enough detail to 
  874. know where the leak is occurring. However, it is possible that the memory 
  875. object is huge. For instance, debugging the usage of the PM APIs is very 
  876. difficult because several PMGRE memory objects can each be many megabytes large 
  877. and sparsely populated. The object level memory leak detector gives detailed 
  878. information about each page state within the memory object as it changes. 
  879.  
  880. In the example of object level memory leak detection below, the memory object 
  881. we are working with starts at linear address 00090000 and contains 16 pages. 
  882. The states of the pages, while tracing the memory object, are represented by 
  883. lower case letters with a summary line labeled "state counts." A page can be in 
  884. any one of ten different states; the states, listed in the order shown in the 
  885. "state counts" line, are: uncommitted (.=), special system (?=), allocate on 
  886. demand (a=), claimable (c=), idle (i=), to be loaded (l=), present (p=), 
  887. resident (r=), swapped (s=) and UVirt (u=). The lines labeled with "dif" at the 
  888. beginning indicate pages whose states have changed since the last data capture. 
  889. If the "dif" line contains a "." then the state has not changed, otherwise a 
  890. capital letter indicates which line below contains an explanation of how the 
  891. page state changed. 
  892.  
  893. Leak detection for Process with PID = 0882, name = LAMAIL,
  894.   linear requested = 00090000, object start linear = 00090000,
  895.   object has 16 pages:
  896. < End of THESEUS2 (v 2.0.1c) output @ 16:49:50 on 3-3-1994 >
  897. Use the 'Function' pull-down to start and stop the data collection.
  898. Previous sample will no longer be used as the base.
  899. < End of THESEUS2 (v 2.0.1c) output @ 16:49:55 on 3-3-1994 >
  900. The data captured is:
  901. Page states, starting with the page at 00090000
  902. sssspsssssspp
  903. state counts: .=3, ?=0, a=0, c=0, i=0, l=0, p=3, r=0, s=10, u=0
  904. Leak data captured.
  905. < End of THESEUS2 (v 2.0.1c) output @ 16:50:00 on 3-3-1994 >
  906. Previous sample will not be used as the base.
  907. Periodic update started with interval of 0:05.
  908. < End of THESEUS2 (v 2.0.1c) output @ 16:50:05 on 3-3-1994 >
  909. old .slspssissppp
  910. new aplspssispppp
  911. dif AB.......C...
  912. dif address    old state            new state
  913. A:  00090000   uncommitted          allocate on demand
  914. B:  00091000   swapped              present
  915. C:  00099000   swapped              present
  916. < End of THESEUS2 (v 2.0.1c) output @ 16:50:10 on 3-3-1994 >
  917. old aplspssispppp
  918. new pslspssispppp
  919. dif AB...........
  920. dif address    old state            new state
  921. A:  00090000   allocate on demand   present
  922. B:  00091000   present              swapped
  923. < End of THESEUS2 (v 2.0.1c) output @ 16:50:15 on 3-3-1994 >
  924. Periodic update stopped.
  925. < End of THESEUS2 (v 2.0.1c) output @ 16:50:20 on 3-3-1994 >
  926. Leak data compared.
  927. old pslspssispppp
  928. new splspssispppp
  929. dif AB...........
  930. dif address    old state            new state
  931. A:  00090000   present              swapped
  932. B:  00091000   swapped              present
  933. < End of THESEUS2 (v 2.0.1c) output @ 16:50:25 on 3-3-1994 >
  934.  
  935. In a large and sparsely populated memory object, the object level memory leak 
  936. detector is invaluable when looking for memory usage patterns or for pages that 
  937. are changing during processing. This function is used most often when a 
  938. particular memory object is suspected of leaking when a particular transaction 
  939. is executed. It is possible to capture the memory objects state, execute the 
  940. transaction, capture the changed state and ask Theseus2 to compare the before 
  941. and after page states. The pages within the memory object that changed are 
  942. obvious; the before and after contents of the pages is also helpful in 
  943. determining what part of the code is responsible for the leak. Once the memory 
  944. contents are known (implying that the process and executable responsible for 
  945. the object are also known), it is not difficult to find a developer who 
  946. recognizes what is going on. The developer who recognizes the executable, the 
  947. process, the memory object and its contents, owns the responsibility for fixing 
  948. the leak. At times developers have been known to flee when approached with what 
  949. looks like memory object dumps. 
  950.  
  951.  
  952. ΓòÉΓòÉΓòÉ 7.3. Detecting Memory Leaks ΓòÉΓòÉΓòÉ
  953.  
  954. There are several ways to detect memory leaks; some are good, some are bad, 
  955. some are fast and some are slow. This section discusses a few of the bad ones 
  956. so that you will avoid them, and then suggests a few good techniques that have 
  957. proven valuable. 
  958.  
  959.  
  960. ΓòÉΓòÉΓòÉ 7.3.1. SWAPPER.DAT File Growth ΓòÉΓòÉΓòÉ
  961.  
  962. We have included this section because many developers and testers tend to 
  963. equate SWAPPER.DAT file growth with memory leaks. While it is true that memory 
  964. leaks usually cause swap file growth, the converse is not true. Swap file 
  965. growth can occur, and be sustained, when there is no memory leak, and memory 
  966. leaks do not always reveal themselves in swap file growth. The lesson here is: 
  967. Do not rely on utilities that merely report SWAPPER.DAT size (e.g. SWAPMON)! 
  968. Such utilities, for the purpose of memory leaks, are not worth the resources 
  969. needed to run them - even if they were free. The reason is not only are they 
  970. not an accurate picture of what is occurring, they are misleading; leading to 
  971. errors of commission (yelling wolf when there is no wolf). We have answered 
  972. countless such calls and have acquired quite the distaste for such utilities as 
  973. indicators of memory leaks. If you must monitor the swap file, then use 
  974. Theseus2 so that you know how many pages within the file are used and how many 
  975. are free. If the number of pages used grows consistently with multiple 
  976. executions of the same case, you may have a memory leak. Note also that OS/2's 
  977. algorithm for shrinking the swap file is complex, containing several or'd 
  978. conditions; if any one of the or'd conditions fails, then the swap file will 
  979. not shrink in size. Even if the swap file does shrink in size the rate is much 
  980. slower than its rate of growth. 
  981.  
  982.  
  983. ΓòÉΓòÉΓòÉ 7.3.2. Multiple C Runtime Libraries ΓòÉΓòÉΓòÉ
  984.  
  985. We include a section about multiple runtime libraries in a paper about memory 
  986. leaks because multiple runtime libraries can be a tricky pit to discover that 
  987. you have fallen into. As you know, most compilers require that you not ship a 
  988. runtime library with your product that has the same name as the runtime they 
  989. shipped to you. For example, if you use the C Set/2 compiler, you cannot ship a 
  990. runtime library that has the name DDE4SBS, DDE4MBS or any name that they ship 
  991. as a DLL. Usually developers rebuild the compiler's runtime with another name. 
  992.  
  993. Now the tricky part comes with large development efforts where several 
  994. components each create their own runtime libraries, or when you use several 
  995. versions of the same compiler, each with a uniquely renamed runtime. With 
  996. multiple runtimes every developer must be cognizant of which runtime he 
  997. allocating memory from, so that he can deallocate the memory from the same 
  998. runtime; runtimes do not communicate with each other. This is a particularly 
  999. difficult situation if you have a design that specifies that one module 
  1000. allocate and another module deallocate memory. Either ensure that both modules 
  1001. have been compiled with the same runtime or provide APIs for each other to 
  1002. call. 
  1003.  
  1004.  
  1005. ΓòÉΓòÉΓòÉ 8. Detection and Solution Examples ΓòÉΓòÉΓòÉ
  1006.  
  1007. In this last section of the paper we want to show you how we detected and fixed 
  1008. several common types of leaks. The examples are relatively simple but 
  1009. sufficient to indicate the steps you may want to take first when fixing memory 
  1010. leaks. Below we have included the source code of the program that we used to 
  1011. generate most of the examples in this section; we compiled the source with the 
  1012. DEBUG and __DEBUG_ALLOC__ macros on. It will be helpful to refer back to the 
  1013. source to see each error as we detect and fix it. 
  1014.  
  1015.  
  1016. ΓòÉΓòÉΓòÉ 8.1. Example Program: MemLeaks ΓòÉΓòÉΓòÉ
  1017.  
  1018. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1019.    MemLeaks.h
  1020.  
  1021.    debug defines
  1022. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1023. #ifdef DEBUG
  1024.    #define DEBUG_CODE(code)                \
  1025.            code
  1026.  
  1027.    #define DEBUG_MSG(msg)                  \
  1028.            printf(msg);                    \
  1029.            fflush(stdout)
  1030.  
  1031.    #define DEBUG_MSG1(msg, p1)             \
  1032.            printf(msg, p1);                \
  1033.            fflush(stdout)
  1034.  
  1035.    #define DEBUG_MSG2(msg, p1, p2)         \
  1036.            printf(msg, p1, p2);            \
  1037.            fflush(stdout)
  1038.  
  1039.    #define DEBUG_MSG3(msg, p1, p2, p3)     \
  1040.            printf(msg, p1, p2, p3);        \
  1041.            fflush(stdout)
  1042.  
  1043.    #define DEBUG_MSG4(msg, p1, p2, p3, p4) \
  1044.            printf(msg, p1, p2, p3, p4);    \
  1045.            fflush(stdout)
  1046. #else
  1047.    #define DEBUG_CODE(code)
  1048.    #define DEBUG_MSG(msg)
  1049.    #define DEBUG_MSG1(msg, p1)
  1050.    #define DEBUG_MSG2(msg, p1, p2)
  1051.    #define DEBUG_MSG3(msg, p1, p2, p3)
  1052.    #define DEBUG_MSG4(msg, p1, p2, p3, p4)
  1053. #endif
  1054.  
  1055.   1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1056.   2    MemLeaks.c
  1057.   3
  1058.   4    MODULE:       MemLeak                                           1.24.94
  1059.   5
  1060.   6    AUTHOR:       SD Hargis
  1061.   7
  1062.   8    FUNCTION:     Memory leak examples used with a White paper on detecting
  1063.   9                  and fixing memory leaks. Several kinds of leaks are demon-
  1064.  10                  strated by this program.
  1065.  11
  1066.  12    DESCRIPTION:  The type of memory problems demonstrated in this program:
  1067.  13                     1) trying to free memory allocated by DosAllocMem;
  1068.  14                     2) memory overwrites;
  1069.  15                     3) memory leak;
  1070.  16
  1071.  17    INPUTS:       free       : A parameter indicating that memory should be
  1072.  18                               freed; this is an optional parameter, its
  1073.  19                               absence indicates that memory should not be
  1074.  20                               freed.
  1075.  21                  User will be prompted for a string.
  1076.  22
  1077.  23    OUTPUTS:      none       :
  1078.  24                  There is some screen output.
  1079.  25
  1080.  26    ERROR CODES:  >= 0   successful completion
  1081.  27                  <  0   error condition occurred
  1082.  28
  1083.  29 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1084.  30
  1085.  31 #define ARRAY_SIZE 8
  1086.  32
  1087.  33 #include <os2def.h>
  1088.  34 #include <stdlib.h>
  1089.  35 #include <malloc.h>
  1090.  36 #include <stdio.h>
  1091.  37 #include <bsedos.h>
  1092.  38 #include <bsememf.h>
  1093.  39 #include "memleaks.h"
  1094.  40
  1095.  41
  1096.  42 APIRET main(int argc, char *argv[])
  1097.  43 {
  1098.  44                APIRET  rc=0;
  1099.  45                  char *array=NULL;
  1100.  46                   int *a=NULL;
  1101.  47                 PVOID  pDOS=NULL;
  1102.  48
  1103.  49 /* DEFINE VARIABLES */
  1104.  50
  1105.  51
  1106.  52 /* INITIALIZE VARIABLES */
  1107.  53
  1108.  54
  1109.  55 /* MAIN LINE PROCESSING */
  1110.  56    if   (argc >  2)
  1111.  57    {
  1112.  58       printf("You did not correctly specify the parameters.\n");
  1113.  59       printf("Necessary parameters, in order, are:\n");
  1114.  60
  1115.  61       if (argv[1] != NULL)
  1116.  62       {
  1117.  63          printf("\nfree : [optional parameter]\n");
  1118.  64       }
  1119.  65 DEBUG_CODE(
  1120.  66       else
  1121.  67       {
  1122.  68          printf("\nNo input parameters, good.\n\n");
  1123.  69       } /* endif */
  1124.  70 )
  1125.  71
  1126.  72       printf("Please reenter \"%s\" followed by valid parameters.\n"
  1127.  73              "\n", argv[0]);
  1128.  74       goto end;
  1129.  75    } /* end if */
  1130.  76
  1131.  77
  1132.  78    /* dosallocmem memory for an array */
  1133.  79    if (rc = DosAllocMem (&pDOS, (ULONG) ARRAY_SIZE, fALLOC))
  1134.  80    {
  1135.  81       printf("%s: DosAllocMem error at %d with %ld.\n", __FILE__,
  1136.  82              __LINE__-3, rc);
  1137.  83       rc = -1;
  1138.  84       goto end1;
  1139.  85    }
  1140.  86 DEBUG_CODE(
  1141.  87    else
  1142.  88   {
  1143.  89       printf("%d in %s: %d bytes DosAllocMem'd @ %p.\n", __LINE__-10,
  1144.  90             __FILE__, ARRAY_SIZE, &pDOS);
  1145.  91   }
  1146.  92 )
  1147.  93
  1148.  94
  1149.  95    /* malloc memory for an array and an integer */
  1150.  96    if (! (array = malloc(ARRAY_SIZE)))
  1151.  97    {
  1152.  98       printf("%s: no memory to malloc at %d.\n", __FILE__, __LINE__-2);
  1153.  99       rc = -1;
  1154. 100       goto end2;
  1155. 101    }
  1156. 102 DEBUG_CODE(
  1157. 103    else
  1158. 104    {
  1159. 105       printf("%d in %s: %d bytes malloc'd @ %p.\n", __LINE__-9, __FILE__,
  1160. 106              ARRAY_SIZE, array);
  1161. 107    }
  1162. 108 )
  1163. 109
  1164. 110    if (! (a = malloc(sizeof(int))))
  1165. 111    {
  1166. 112       printf("%s: no memory to malloc at %d.\n", __FILE__, __LINE__-2);
  1167. 113       rc = -1;
  1168. 114       goto end3;
  1169. 115    }
  1170. 116 DEBUG_CODE(
  1171. 117    else
  1172. 118    {
  1173. 119       printf("%d in %s: %d bytes malloc'd @ %p.\n", __LINE__-9, __FILE__,
  1174. 120              sizeof(int), a);
  1175. 121    }
  1176. 122 )
  1177. 123
  1178. 124    /* have user input an integer and characters for the array */
  1179. 125    printf("\nType an integer (-32768 - 32767) & press the <Enter> key.\n");
  1180. 126    scanf("%d", a);
  1181. 127
  1182. 128    /* we are using malloc'd memory so free dosallocmem memory */
  1183. 129    free(&pDOS);
  1184. 130
  1185. 131    printf("Type some characters and press the <Enter> key.\n");
  1186. 132    scanf("%s", array);
  1187. 133    printf("\nCheers! The number you entered was %d &\n"
  1188. 134           "the characters you entered were \"%s\".\n", *a, array);
  1189. 135
  1190. 136
  1191. 137 end3:
  1192. 138    if (argv[1]) free(a);
  1193. 139 end2:
  1194. 140    if (argv[1]) free(array);
  1195. 141 end1:
  1196. 142    if (argv[1]) DosFreeMem(pDOS);
  1197. 143 end:
  1198. 144
  1199. 145 #ifdef __DEBUG_ALLOC__
  1200. 146    _dump_allocated(16);
  1201. 147 #endif
  1202. 148
  1203. 149    return(rc);
  1204. 150 /* main */
  1205.  
  1206.  
  1207. ΓòÉΓòÉΓòÉ 8.2. Normal Execution ΓòÉΓòÉΓòÉ
  1208.  
  1209. This is how the program looks when it executes as it should. Note that to get 
  1210. the program to execute flawlessly we had to correct the error found in the next 
  1211. section. Bold letters are user typed responses. 
  1212.  
  1213. [D:\WORK\LEAKS] memleaks.exe free
  1214. 79 in MEMLEAKS.C: 8 bytes DosAllocMem'd @ 2986C.
  1215. 96 in MEMLEAKS.C: 8 bytes malloc'd @ 70250.
  1216. 110 in MEMLEAKS.C: 4 bytes malloc'd @ 70270.
  1217.  
  1218. Type an integer (-32768 - 32767) & press the <Enter> key.
  1219. 12345
  1220. Type some characters and press the <Enter> key.
  1221. abcdefg
  1222.  
  1223. Cheers! The number you entered was 12345 &
  1224. the characters you entered were "abcdefg".
  1225.  
  1226. ΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉ
  1227.                  START OF DUMP OF ALLOCATED MEMORY BLOCKS
  1228. ΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉ
  1229.                  END OF DUMP OF ALLOCATED MEMORY BLOCKS
  1230. ΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉ
  1231.  
  1232.  
  1233. ΓòÉΓòÉΓòÉ 8.3. Bad Memory Pointers ΓòÉΓòÉΓòÉ
  1234.  
  1235. This execution of the program is exactly as the source is shown above and 
  1236. demonstrates how easy it can be to locate some memory errors with the correct 
  1237. tools. In this case we will locate an invalid pointer passed to a memory 
  1238. management function. 
  1239.  
  1240. [D:\WORK\LEAKS] memleaks.exe free
  1241. 79 in MEMLEAKS.C: 8 bytes DosAllocMem'd @ 2986C.
  1242. 96 in MEMLEAKS.C: 8 bytes malloc'd @ 70250.
  1243. 110 in MEMLEAKS.C: 4 bytes malloc'd @ 70270.
  1244.  
  1245. Type an integer (-32768 - 32767) & press the <Enter> key.
  1246. 12345
  1247. The invalid memory block address 0x0002987C
  1248. was passed in at line 129 of MEMLEAKS.C.
  1249.  
  1250. Look at that, an error on line 129. How easy to spot. Examining the line in 
  1251. question we discover that we are trying to free memory allocated by line 79. 
  1252. The allocation method on line 79 is DosAllocMem; so the error is calling free 
  1253. with a pointer received from DosAllocMem. The proper call is DosFreeMem. 
  1254.  
  1255. Let us trace how the error was caught. At the beginning of every C/C++ debug 
  1256. memory management call, _heap_check is called. As _heap_check went through the 
  1257. heap it noticed that the pointer passed to free was not a pointer that it was 
  1258. managing. Thus it aborted the process with an appropriate message. This type of 
  1259. memory error is found only when the compiler's debug memory management 
  1260. functions are turned on. If you read the library reference where it discusses 
  1261. the free function it says that calls with an invalid pointer are ignored, 
  1262. however, the behavior is undefined. We have seen repeated calls to free with 
  1263. the same pointer cause intermittent heap corruption. Such errors are hard to 
  1264. find and not worth the trouble of not using the tools available to eradicate 
  1265. them. 
  1266.  
  1267. For our program we will fix line 129 by commenting it out. Future executions of 
  1268. MemLeaks.exe will be with this update. 
  1269.  
  1270.  
  1271. ΓòÉΓòÉΓòÉ 8.4. Memory Left on the Heap ΓòÉΓòÉΓòÉ
  1272.  
  1273. OK, now we are going to execute MemLeaks.exe without any arguments/parameters. 
  1274. What do the diagnostic messages indicate? 
  1275.  
  1276. [D:\WORK\LEAKS] memleaks.exe
  1277. 79 in MEMLEAKS.C: 8 bytes DosAllocMem'd @ 2986C.
  1278. 96 in MEMLEAKS.C: 8 bytes malloc'd @ 70250.
  1279. 110 in MEMLEAKS.C: 4 bytes malloc'd @ 70270.
  1280.  
  1281. Type an integer (-32768 - 32767) & press the <Enter> key.
  1282. 12345
  1283. Type some characters and press the <Enter> key.
  1284. abcdefg
  1285.  
  1286. Cheers! The number you entered was 12345 &
  1287. the characters you entered were "abcdefg".
  1288.  
  1289. ΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉ
  1290.                  START OF DUMP OF ALLOCATED MEMORY BLOCKS
  1291. ΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉ
  1292. Address: 0x00070270      Size: 0x00000004 (4)
  1293. This memory block was (re)allocated at line number 110 in MEMLEAKS.C.
  1294. Memory contents:  39300000                               [90..            ]
  1295. ΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉ
  1296. Address: 0x00070250      Size: 0x00000008 (8)
  1297. This memory block was (re)allocated at line number 96 in MEMLEAKS.C.
  1298. Memory contents:  61626364 65666700                      [abcdefg.        ]
  1299. ΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉ
  1300.                  END OF DUMP OF ALLOCATED MEMORY BLOCKS
  1301. ΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉ
  1302.  
  1303. The "DUMP OF ALLOCATED MEMORY BLOCKS" is generated by the _dump_allocated call 
  1304. that is ifdef'd at the end of the program, just before returning control to the 
  1305. operating system. _dump_allocated printed out the first 16 bytes of each memory 
  1306. object that is still being managed by the debug memory management functions. 
  1307. Obviously we have left memory on the heap - Yes, a memory leak! How easy it is 
  1308. to see that the memory was left on the heap because we malloc'd it but never 
  1309. free'd it. When we include a parameter to the execution of MemLeaks.exe the if 
  1310. statements on lines 138-142 are executed and the memory is freed. 
  1311.  
  1312. You're getting good. Let's move on to memory overwrite errors; they will 
  1313. challenge your newly found expertise. 
  1314.  
  1315.  
  1316. ΓòÉΓòÉΓòÉ 8.5. Memory Overwrites ΓòÉΓòÉΓòÉ
  1317.  
  1318. Since this type of error is hard to debug let us set the stage for what is to 
  1319. occur. On line 96 of the source we malloc enough room for an array of 8 bytes 
  1320. (see also line 31). The C Set/2 and C/C++ Tools compilers do not necessarily 
  1321. allocate exactly 8 bytes. It happens to allocate according to the following 
  1322. formula, where we have asked for x bytes: x + 16, rounded up to the next power 
  1323. of 2. So when we asked for 8 bytes we really got 32 bytes. And on line 110 when 
  1324. we asked for 4 bytes, we really got another 32 bytes. You can confirm this by 
  1325. noting that the first malloc returned the address of 70250 and the second 
  1326. malloc returned 70270. The difference being hex 20 or decimal 32. Thus the 
  1327. successive mallocs are 32 bytes apart. Isn't math fun! 
  1328.  
  1329. Now what would happen if, while reading in our array of characters, it was 
  1330. longer than 32 bytes? Wouldn't the compiler limit us to the 8 bytes that we 
  1331. asked for, or at least 16 (32 allocated - 16 for book keeping)? No. As we will 
  1332. see shortly, it is possible to go beyond the size of the memory object you 
  1333. allocated and overwrite onto the next object. Oh these errors are hard to find 
  1334. without the compilers assistance. Often memory overwrite errors are innocuous 
  1335. because the data does not go beyond the padding that the compiler allocated due 
  1336. to its rounding up to the next power of 2, but no-one wants to bet the quality 
  1337. of their product on all such errors being innocuous. Below is what MemLeaks.exe 
  1338. looks like when a memory overwrite occurs. 
  1339.  
  1340. [D:\WORK\LEAKS] memleaks.exe
  1341. 79 in MEMLEAKS.C: 8 bytes DosAllocMem'd @ 2986C.
  1342. 96 in MEMLEAKS.C: 8 bytes malloc'd @ 70250.
  1343. 110 in MEMLEAKS.C: 4 bytes malloc'd @ 70270.
  1344.  
  1345. Type an integer (-32768 - 32767) & press the <Enter> key.
  1346. 12345
  1347. Type some characters and press the <Enter> key.
  1348. abcdefghijklmnopqrstuvwxyzabcdefghij
  1349.  
  1350. Cheers! The number you entered was 1785292903 &
  1351. the characters you entered were "abcdefghijklmnopqrstuvwxyzabcdefghij".
  1352.  
  1353. Memory was overwritten before the allocated memory block which starts at
  1354. address 0x00070270.
  1355. The first eight bytes of the memory block (in hex) are: 6768696A00A5B5A5.
  1356. The file name and line number are not available.
  1357.  
  1358. Shucks, no file name or line number. Boy what a mess we are in; most data is 
  1359. correct and sometimes, for no apparent reason at all, some data goes berserk on 
  1360. us. Well, not all is lost; we have the address where the corruption is 
  1361. occurring. The compiler figured that much out by surrounding the memory that we 
  1362. allocated with sentinels. The sentinel is a xD5A5 at the front and a xB5A5B5A5 
  1363. at the end of the memory, surrounding only the number of bytes that we asked to 
  1364. be allocated. 
  1365.  
  1366. The collection of screen dumps below shows how we used IPMD, the C/C++ 
  1367. debugger, to gain more information about memory overwrite errors and fix them. 
  1368. We start with the initial IPMD screens. Initial IPMD screen 
  1369.  
  1370. Once the initial screens are up you can double click on the line numbers where 
  1371. you want to set a break point. Execution stops at each break point before the 
  1372. line is executed. For our program we will break at line 79 where the allocation 
  1373. of memory begins. A break point is set 
  1374.  
  1375. Clicking on the storage icon at the top of the screen will bring up a window 
  1376. that shows you the contents of memory locations. Click on the storage icon to 
  1377. see data in memory 
  1378.  
  1379. Click on a number in the address section and type in the address that you want 
  1380. to see. Since our memory overwrite problem was at 70270 we will display the 
  1381. contents of memory start a few words before that. Type in the memory address 
  1382. whose contents you want to see 
  1383.  
  1384. Now click on the green run button at the top and the program will run until the 
  1385. next break point is met. We have placed break points at strategic places in the 
  1386. program; the alternative is to "step over" each function. Clicking the green 
  1387. run button executes the program until the next break point 
  1388.  
  1389. While executing your program under IPMD you can "step over," "step into," "step 
  1390. debug," "step return" or run the functions. Stepping over (executing the line 
  1391. and all lower level function calls) lines of code seems to be the most useful 
  1392. to begin with. Execution can proceed one function call at a time 
  1393.  
  1394. Note that each memory area that we malloc'd is evident by the sentinels. The 
  1395. sentinels are immediately before and after the memory that we requested, and 
  1396. only the amount of memory that we requested is available to be used. It can be 
  1397. helpful to note that 16 bytes before the address that is returned to us as 
  1398. allocated, is for memory book keeping information. See how the bytes 
  1399. immediately above and below the mouse pointer shows the length of the memory 
  1400. that was requested. Remember that the numeric information in memory is byte 
  1401. reversed (character information is not byte reversed), thus 08000000 in memory 
  1402. in equivalent to 00000008 in the way that we look at it. Between this 
  1403. information and the sentinels you should be able to locate almost any allocated 
  1404. memory field. 
  1405.  
  1406. o Beginning sentinel: xD5A5 
  1407.  
  1408. o Ending sentinel: xB5A5B5A5 
  1409.  
  1410. o Length field: (pointer returned from allocation) - 16 
  1411.  
  1412. While stepping over the scanf on line 126 we need to go to the session that the 
  1413. program was running in and type in a response to the prompt to input a number. 
  1414. The number we are using is still 12345, which is 3039 in hex, which is stored 
  1415. as 39300000 in memory. The memory contents now show the number we input 
  1416.  
  1417. While stepping over the scanf on line 132 we switched to the running program 
  1418. and input more than 8 characters. Stepping over lines of code allows us to 
  1419. clearly see which line is the offender. As each line is stepped over watch the 
  1420. storage window. A line of code will overwrite memory objects. In this case it 
  1421. is the scanf on line 132. The memory overwrite is clearly indicated and so is 
  1422. the offending code 
  1423.  
  1424. By looking at the last storage screen you can see that the behavior of the 
  1425. program depends on how much memory you overwrite. In this case we overwrote the 
  1426. book keeping information, beginning sentinel and most of the contents of the 
  1427. integer we previously input. Note that the program continued and reported a 
  1428. wrong number; we input the integer 12345 and it is reporting 1785292903 which 
  1429. is x6A696867. Do you see where the number it reported came from? The debug 
  1430. memory management functions catch the memory overwrite 
  1431.  
  1432.  
  1433. ΓòÉΓòÉΓòÉ 8.6. Closing Suggestions ΓòÉΓòÉΓòÉ
  1434.  
  1435. Well, there you have it; most of the knowledge that we have about memory leaks. 
  1436. We discussed what they are, how to detect them, how to find them, how to plug 
  1437. them and what tools to use. We even gave you a pictorial guide of detecting and 
  1438. fixing the most common types of leaks. Our examples were simple, so fixing 
  1439. leaks in your code may require you to work with more noise and less clear 
  1440. logic, but the basic skills are all there now. 
  1441.  
  1442. You may find yourself with a system of programs that has memory leaks and you 
  1443. do not know how to narrow the focus to just 1 component. Here are several ideas 
  1444. that developers, whom we personally know, have tried successfully. 
  1445.  
  1446. o Use a common function to do all allocation and deallocation of memory, and 
  1447.   add some tracking information to that common function. Many developers have 
  1448.   their own versions of this idea. Most ideas include accessing the stack to 
  1449.   print out who the caller is; they also track the pointer returned from 
  1450.   allocating memory, the number of bytes requested and a timestamp. This 
  1451.   information accommodates pairing up allocation and deallocation requests. 
  1452.  
  1453. o If you can get the source code for your compiler, you can supplement memory 
  1454.   allocation and deallocation calls with tracking information. A post-processor 
  1455.   can then be used to digest the information and indicate where one might 
  1456.   focus. It is even possible to build the modified compiler functions into a 
  1457.   DLL with the original compiler functions. At runtime, based on an environment 
  1458.   variable, the DLL can be initialized to use either the modified or the 
  1459.   original version of the memory de/allocation functions. 
  1460.  
  1461. o Build separate components with separate runtime libraries and use Theseus2 to 
  1462.   show which runtime the leak(s) is coming from. Be sure to avoid creating 
  1463.   additional memory leaks since you now have multiple runtime libraries. 
  1464.  
  1465. Remember: Nothing beats having the right tools for the job! 
  1466.  
  1467.  
  1468.  
  1469. ΓòÉΓòÉΓòÉ 9. Leaky Interfaces between C and C++ ΓòÉΓòÉΓòÉ
  1470.  
  1471. When writing functions which allow standard C programs to access C++ objects 
  1472. care must be given when supplying object destructors. If object references are 
  1473. not declared correctly then it is possible that the destructor will not 
  1474. properly free all of the memory that was claimed by the object's constructor 
  1475. and thus result in a memory leak. The symptom is that a pointer is freed but 
  1476. not the object pointed to by the pointer. An example of an object constructor 
  1477. and destructor to be accessed by standard C programs is given below for an 
  1478. object named Trace_Class. Any ANSI C/C++ compiler will behave in the manner 
  1479. indicated by this example. 
  1480.  
  1481. void * TC_Constructor(void)
  1482.    {
  1483.       return (void *) new Trace_Class();
  1484.    }
  1485.  
  1486. void * TC_Destructor(void *pTC)
  1487.    {
  1488.       delete pTC;
  1489.    }
  1490.  
  1491. The constructor above, when called by standard C code, will return a pointer to 
  1492. a newly created instance of an object of type Trace_Class. Note that the 
  1493. pointer to the object instance is returned as a (void *) since this pointer 
  1494. should be considered a reference to opaque data by standard C routines. 
  1495.  
  1496. The destructor above is supposed to free the object created by the call to 
  1497. TC_Constructor. There is an error, however. The declaration of the argument to 
  1498. TC_Destructor is (void *), which is appropriate since that is the same type 
  1499. that is returned by TC_Constructor. However, the C++ delete routine is called 
  1500. with pTC which the compiler translates to free(pTC) since pTC's type is (void 
  1501. *). This will not have the desired effect since properly freeing all of the 
  1502. memory assigned by "new Trace_Class()" requires a call to Trace_Class's 
  1503. destructor. This can be accomplished by properly declaring pTC's type as a 
  1504. pointer to an object of type Trace_Class. The modified TC_Destructor that frees 
  1505. the objects memory completely is: 
  1506.  
  1507. void * TC_Destructor(void *pTC)
  1508.    {
  1509.       delete (Trace_Class *)pTC;
  1510.    }
  1511.  
  1512. The above change now allows the compiler to translate the above to a call to 
  1513. the Trace_Class destructor with a pointer to the instance held in pTC. 
  1514.  
  1515.  
  1516. ΓòÉΓòÉΓòÉ 10. Forum Q & A about Malloc ΓòÉΓòÉΓòÉ
  1517.  
  1518. Like many developers we have had occasion to question the inner workings of 
  1519. C/C++ memory management. Below is a compilation of questions and answers that 
  1520. we found to be helpful. We hope that you do too. The edited excerpts are from 
  1521. the C-SET2 FORUM and C-SET2 ANSWERS. In future releases any implementation 
  1522. details below the API level are compiler specific and subject to improvements 
  1523. or other changes without notice. 
  1524.  
  1525. o How does malloc work internally, ie. how much memory does it really allocate? 
  1526.   If a program uses malloc exclusively, will C-Set/2 then take care of all 
  1527.   memory management related matters (such as de/committing pages)? Are there 
  1528.   any limits to be observed? 
  1529.  
  1530. o Internally, malloc adds 16 to the size requested, rounds it up to the next 
  1531.   even power of 2, and grabs that much memory. If malloc has a block of that 
  1532.   size available, it gives it to you without going to the OS. Otherwise, it 
  1533.   grabs a block of at least 4K bytes from the OS (since the page size is 4K). 
  1534.   Anything extra is kept around for later calls to malloc. When you call 
  1535.   free(), the memory is not returned to the OS, but is kept around for later 
  1536.   allocation. If you want to return memory to the OS, you must call _heapmin(). 
  1537.  
  1538.   The algorithm is the Berkeley Bucket Algorithm. It's very fast, but has a 
  1539.   tendency to waste memory with some allocation sizes. 
  1540.  
  1541. o Can somebody give me more details or a reference to details for the the 
  1542.   Berkeley Bucket Algorithm. 
  1543.  
  1544. o Allocating memory in sizes which are powers of 2 allows us to write a very 
  1545.   simple, very fast, malloc routine. If the memory were cut up into the exact 
  1546.   size that you malloc (plus, of course, overhead), we would have to search 
  1547.   what was on our heap. The Berkeley Bucket algorithm allows us to check in one 
  1548.   place to see if we have memory for you. A search algorithm is nowhere near as 
  1549.   fast. 
  1550.  
  1551. o The rounding up to the next even power of 2 disturbs me a little. When 
  1552.   getting into larger sizes this could alloc a great deal, i.e. asking for 33K 
  1553.   would allocate 64K (if I understand correctly what was said). And would the 
  1554.   part from 33K to 64K be available to be used in a next malloc or is it 
  1555.   assumed to be part of the 33K request? 
  1556.  
  1557.   Also out of curiosity, does malloc allocate a large area uncommitted, and 
  1558.   commit pages out of it, or every time it needs to ask OS/2 for memory it does 
  1559.   a DosAllocMem of just that size? 
  1560.  
  1561. o Yes - if you malloc 33K, you really get 64K.  the remaining 31K is wasted 
  1562.   storage (but it only exists on the swapper, not in real memory). (Authors 
  1563.   note: In this scenario 36K of physical memory will be committed when it is 
  1564.   accessed.  The amount is 36K because 36 is a multiple of 4 and memory is 
  1565.   committed in 4K chunks; in other words, virtual memory is backed by physical 
  1566.   memory, when accessed, in 4K chunks. It is possible that this 36K could be 
  1567.   swapped, but not necessary. In OS/2 v1.x space in the swap file was reserved, 
  1568.   in OS/2 v2.x that is no longer the case. The remaining 28K is allocated 
  1569.   (virtual) memory only.) 
  1570.  
  1571.   malloc calls DosAllocMem to allocate blocks which are a multiple of 4K bytes 
  1572.   (same size as a memory page). It doesn't use DosSubAlloc to cut them up, 
  1573.   since the performance of DosSubAlloc isn't that great. The Berkely Bucket 
  1574.   algorithm optimizes speed, not total memory used. (Authors note: The 
  1575.   sentences above state that DosAllocMem allocates memory in 4K chunks; that is 
  1576.   most of the story, but not all of it. DosAllocMem allocates virtual memory in 
  1577.   4K chunks; virtual memory is backed by physical memory in 4K chunks. For 
  1578.   memory objects that are used by 16-bit code, OS/2 uses a tiled LDT that has 
  1579.   8192 descriptor slots. Each descriptor maps a maximum of 64K. If you 
  1580.   DosAllocMem a tiled object a descriptor is used and that 64K of virtual 
  1581.   address space is unavailable even if the actual size of the object is only 
  1582.   33K. So if 33K is DosAllocMem'd, 64K of virtual memory becomes unavailable, 
  1583.   36K will be allocated and the allocated memory is backed by physical memory 
  1584.   in 4K chunks when it is accessed.) 
  1585.  
  1586.   You may be overlooking some significant details concerning the memory 
  1587.   management in OS/2. OS/2 uses what is called "lazy page allocation" this 
  1588.   means that if I DosAllocMem 10 megabytes, all the OS does is set up the page 
  1589.   table entries so they are marked "not-present", and remember the range of 
  1590.   entries. *Nothing* else happens until you actually *access* the page. At that 
  1591.   point, the OS creates a 0 filled page for you. Since pages are 4K in size, if 
  1592.   I only use the first 10K of that 10 Meg, only 12K worth of real memory is 
  1593.   taken. (plus the overhead for the page table entries) 
  1594.  
  1595.   The malloc routines in the library take advantage of this (very good) 
  1596.   allocation strategy on the part of the OS, to keep the malloc and free code 
  1597.   simple and fast. Committing and de-committing memory involves calling ring 0 
  1598.   routines in the OS -- This will cost about 400 clocks just to do the 
  1599.   privilege transitions. malloc and free currently take less time than this to 
  1600.   do *all* their work. 
  1601.  
  1602.   P.S.  Please note that BSD implementations of Unix use this algorithm too. 
  1603.  
  1604. o If I allocate 10Megs of memory, apart from what you describe, doesn't that 
  1605.   also take up 10Megs of SWAPPER space, if that memory is allocated as 
  1606.   committed, or does the reservation of SWAPPER.DAT space only occur at the 
  1607.   first memory hit on each page? 
  1608.  
  1609. o Does the OS do the allocation on the hit of each page? The answer I always 
  1610.   got was that the *only* thing created at the time DosAllocMem is called are 
  1611.   the page table entries. 
  1612.  
  1613.   P.S. Lots of UNIX programs assume the OS does lazy page allocation. 
  1614.  
  1615. o Also, if you have a process that periodically requires large amounts of 
  1616.   memory and then doesn't require it for awhile, does it make sense to call 
  1617.   _heapmin to return it? I'm thinking of a process that maybe is refreshing 
  1618.   data from the host say every 30 minutes and during the refresh would need 
  1619.   large amounts of data in memory but then when done it doesn't need it. This 
  1620.   doesn't take up memory from other processes since it will be swapped out, but 
  1621.   it still takes up all that room on the swapper. Could be a couple meg of 
  1622.   memory. 
  1623.  
  1624. o By all means, if you allocate a lot of memory, use it for a short time, and 
  1625.   then free it, and then "go to sleep" for a long period, use _heapmin. It's 
  1626.   not required, but will free up swapper space. Makes your program a "good 
  1627.   citizen". 
  1628.  
  1629. o Use _alloca to allocate dynamic storage that is specific to a function. It 
  1630.   allocates from the stack and the storage is automatically freed when the 
  1631.   function returns; make sure the function is short-lived and does not use all 
  1632.   of the stack space. 
  1633.  
  1634. o Use malloc to allocate storage that is small or will be resized. If you have 
  1635.   hundreds of small mallocs you should consider doing a large malloc and 
  1636.   managing the small pieces yourself. 
  1637.  
  1638. o Use DosAllocMem for allocations greater than 3,000 to 4,000 bytes. 
  1639.  
  1640. o Ensure that objects favoring DWORD alignment are DWORD aligned. malloc and 
  1641.   _alloca always return storage that is DWORD aligned, so keep objects within 
  1642.   that storage properly aligned. 
  1643.  
  1644. o WORD align shorts. 
  1645.  
  1646. o DWORD align int long and float. 
  1647.  
  1648. o QWORD align doubles. 
  1649.