OCC22256 Add mechanism based on malloc/free callback for debugging memory problems
[occt.git] / src / OSD / OSD_MAllocHook.hxx
1 // File:        OSD_MAllocHook.hxx
2 // Created:     03.02.2011
3 // Author:      Mikhail SAZONOV
4 // Copyright:   Open CASCADE S.A.S. 2011
5
6 #ifndef _OSD_MAllocHook_HeaderFile
7 #define _OSD_MAllocHook_HeaderFile
8
9 #include <Standard_TypeDef.hxx>
10 #include <Standard_Mutex.hxx>
11 #include <stdio.h>
12
13 /**
14  * This class provides the possibility to set callback for memory
15  * allocation/deallocation.
16  * On MS Windows, it works only in Debug builds. It relies on the
17  * debug CRT function _CrtSetAllocHook (see MSDN for help).
18  */
19 class OSD_MAllocHook
20 {
21 public:
22   /**
23    * Interface of a class that should handle allocation/deallocation events
24    */
25   class Callback
26   {
27   public:
28     //! Allocation event handler
29     /**
30      * It is called when allocation is done
31      * @param theSize
32      *   the size of the memory block in bytes
33      * @param theRequestNum
34      *   the allocation order number of the memory block
35      */
36     virtual void AllocEvent
37                    (size_t      theSize,
38                     long        theRequestNum) = 0;
39
40     //! Freeing event handler
41     /**
42      * It is called when the block is freed
43      * @param theData
44      *   the pointer to the user data section of the memory block
45      * @param theSize
46      *   the size of the memory block in bytes
47      * @param theRequestNum
48      *   the allocation order number of the memory block
49      */
50     virtual void FreeEvent
51                    (void*       theData,
52                     size_t      theSize,
53                     long        theRequestNum) = 0;
54   };
55
56   /**
57    * Implementation of the handler that collects all events
58    * to the log file. It contains the method to generate the report
59    * from the log file.
60    */
61   class LogFileHandler: public Callback
62   {
63   public:
64     //! Constructor
65     Standard_EXPORT LogFileHandler();
66
67     //! Destructor
68     Standard_EXPORT ~LogFileHandler();
69
70     //! Create the file and start collecting events.
71     //! Return false if the file with the given name cannot be created.
72     Standard_EXPORT Standard_Boolean Open(const char* theFileName);
73
74     //! Close the file and stop collecting events
75     Standard_EXPORT void Close();
76
77     //! Make synthesized report on the given log file.
78     /**
79      * Generate an easy to use report in the
80      * new file with the given name, taking the given log file as input.
81      * If theIncludeAlive is true then
82      * include into the report the alive allocation numbers.
83      */
84     Standard_EXPORT static Standard_Boolean MakeReport
85                    (const char* theLogFile,
86                     const char* theOutFile,
87                     const Standard_Boolean theIncludeAlive = Standard_False);
88
89     Standard_EXPORT virtual void AllocEvent(size_t, long);
90     Standard_EXPORT virtual void FreeEvent(void*, size_t, long);
91
92   private:
93     FILE*          myLogFile;
94     Standard_Mutex myMutex;
95     size_t         myBreakSize;
96   };
97
98   /**
99    * Implementation of the handler that collects numbers of
100    * allocations/deallocations for each block size directly in the memory.
101    */
102   class CollectBySize: public Callback
103   {
104   public:
105     //! Constructor
106     Standard_EXPORT CollectBySize();
107
108     //! Destructor
109     Standard_EXPORT ~CollectBySize();
110
111     //! Reset the buffer and start collecting events.
112     Standard_EXPORT void Reset();
113
114     //! Write report in the given file.
115     Standard_EXPORT Standard_Boolean MakeReport(const char* theOutFile);
116
117     Standard_EXPORT virtual void AllocEvent(size_t, long);
118     Standard_EXPORT virtual void FreeEvent(void*, size_t, long);
119
120   private:
121     struct Numbers
122     {
123       int nbAlloc;
124       int nbFree;
125       int nbLeftPeak;
126       Numbers() : nbAlloc(0), nbFree(0), nbLeftPeak(0) {}
127     };
128
129     Standard_Mutex myMutex;
130     Numbers*       myArray;
131     size_t         myTotalLeftSize;
132     size_t         myTotalPeakSize;
133     size_t         myBreakSize;
134   };
135
136   //! Set handler of allocation/deallocation events
137   /**
138    * You can pass here any implementation. For easy start, you can try
139    * with the predefined handler LogFileHandler, which static instance 
140    * is returned by GetLogFileHandler().
141    * To clear the handler, pass NULL here.
142    */
143   Standard_EXPORT static void SetCallback
144                    (Callback* theCB);
145
146   //! Get current handler of allocation/deallocation events
147   Standard_EXPORT static Callback* GetCallback();
148
149   //! Get static instance of LogFileHandler handler
150   Standard_EXPORT static LogFileHandler* GetLogFileHandler();
151
152   //! Get static instance of CollectBySize handler
153   Standard_EXPORT static CollectBySize* GetCollectBySize();
154 };
155
156 #endif /* _OSD_MAllocHook_HeaderFile */