0024834: Allocation of memory for exception message must not throw another exception
[occt.git] / src / Standard / Standard_Failure.cxx
1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <Standard_ErrorHandler.hxx>
16 #include <Standard_Failure.ixx>
17 #include <Standard_TypeMismatch.hxx>
18 #include <Standard_Type.hxx>
19 #include <Standard_Macro.hxx>
20 #include <string.h>
21 #include <Standard_PCharacter.hxx>
22
23 static Standard_CString allocate_message(const Standard_CString AString)
24 {
25   Standard_CString aStr = 0;
26   if(AString) {
27     const Standard_Size aLen = strlen(AString);
28     aStr = (Standard_CString) malloc(aLen+sizeof(Standard_Integer)+1);
29     if (aStr) {
30       Standard_PCharacter pStr=(Standard_PCharacter)aStr;
31       strcpy(pStr+sizeof(Standard_Integer),AString);
32       *((Standard_Integer*)aStr) = 1;
33     }
34   }
35   return aStr;
36 }
37
38 static Standard_CString copy_message(Standard_CString aMessage)
39 {
40   Standard_CString aStr = 0;
41   if(aMessage) {
42     aStr = aMessage;
43     (*((Standard_Integer*)aStr))++;
44   }
45   return aStr;
46 }
47
48 static void deallocate_message(Standard_CString aMessage)
49 {
50   if(aMessage) {
51     (*((Standard_Integer*)aMessage))--;
52     if(*((Standard_Integer*)aMessage)==0)
53       free((void*)aMessage);
54   }
55 }
56
57
58 // ******************************************************************
59 //                           Standard_Failure                       *
60 // ******************************************************************
61 #ifndef NO_CXX_EXCEPTION
62 static Handle(Standard_Failure) RaisedError;
63 #endif
64 // ------------------------------------------------------------------
65 //
66 // ------------------------------------------------------------------
67 Standard_Failure::Standard_Failure ()
68 : myMessage(NULL) 
69 {
70 }
71
72 // ------------------------------------------------------------------
73 // Create returns mutable Failure;
74 // ------------------------------------------------------------------
75 Standard_Failure::Standard_Failure (const Standard_CString AString) 
76 :  myMessage(NULL)
77 {
78   myMessage = allocate_message(AString);
79 }
80
81 Standard_Failure::Standard_Failure (const Standard_Failure& aFailure) 
82 {
83   myMessage = copy_message(aFailure.myMessage);
84 }
85
86 void Standard_Failure::Destroy()
87 {
88   deallocate_message(myMessage);
89 }
90
91 void Standard_Failure::SetMessageString(const Standard_CString AString)
92 {
93   if ( AString == GetMessageString() ) return;
94   deallocate_message(myMessage);
95   myMessage = allocate_message(AString);
96 }
97
98 // ------------------------------------------------------------------
99 // Caught (myclass) returns mutable Failure raises NoSuchObject ;
100 // ------------------------------------------------------------------
101 Handle(Standard_Failure) Standard_Failure::Caught() 
102 {
103 #ifdef NO_CXX_EXCEPTION
104   return Standard_ErrorHandler::LastCaughtError();
105 #else
106   return RaisedError ;
107 #endif
108 }
109
110 // ------------------------------------------------------------------
111 // Raise (myclass; aMessage: CString = "") ;
112 // ------------------------------------------------------------------
113 void Standard_Failure::Raise (const Standard_CString AString) 
114
115   Handle(Standard_Failure) E = new Standard_Failure()  ;
116   E->Reraise (AString) ;
117 }
118
119 // ------------------------------------------------------------------
120 // Raise(myclass; aReason: in out SStream) ;
121 // ------------------------------------------------------------------
122 void Standard_Failure::Raise (const Standard_SStream& AReason) 
123
124   Handle(Standard_Failure) E = new Standard_Failure();
125   E->Reraise (AReason);
126 }
127
128 // ------------------------------------------------------------------
129 // Reraise (me: mutable; aMessage: CString) ;
130 // ------------------------------------------------------------------
131 void Standard_Failure::Reraise (const Standard_CString AString) 
132 {
133   SetMessageString(AString);
134   Reraise();
135 }
136
137 void Standard_Failure::Reraise (const Standard_SStream& AReason) 
138 {
139   SetMessageString(AReason.str().c_str());
140   Reraise();
141 }
142
143 void Standard_Failure::Reraise () 
144 {
145 #ifdef NO_CXX_EXCEPTION
146   Standard_ErrorHandler::Error (this);
147   Standard_ErrorHandler::Abort (this);
148 #else
149   RaisedError = this;
150   Throw();
151 #endif
152 }
153
154 void Standard_Failure::Jump() const 
155 {
156 #if defined (NO_CXX_EXCEPTION) || defined (OCC_CONVERT_SIGNALS)
157   Standard_ErrorHandler::Error (this);
158   Standard_ErrorHandler::Abort (this);
159 #else
160   RaisedError = this;
161   Throw();
162 #endif
163 }
164
165
166 // ------------------------------------------------------------------
167 // Throw (me) is virtual ;
168 // ------------------------------------------------------------------
169 void Standard_Failure::Throw() const
170 {
171 #ifndef NO_CXX_EXCEPTION
172   throw *this;
173 #endif
174 }
175
176 // ------------------------------------------------------------------
177 // Print (me; s: in out OStream) returns OStream;
178 // ------------------------------------------------------------------
179 void Standard_Failure::Print (Standard_OStream& AStream) const
180 {
181 if(myMessage){ 
182     AStream << DynamicType() << ": " << GetMessageString(); 
183  } 
184  else { 
185     AStream << DynamicType();
186  }
187 }
188
189 Handle(Standard_Failure) Standard_Failure::NewInstance(const Standard_CString AString)
190 {
191   return new Standard_Failure(AString)  ;
192 }