?? sec-finalization.html
字號:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><html> <head> <title> Object Finalization </title> <meta name="GENERATOR" content= "Modular DocBook HTML Stylesheet Version 1.45"> <link rel="HOME" title="GTK+ / Gnome Application Development" href="ggad.html"> <link rel="UP" title="The GTK+ Object and Type System" href= "cha-objects.html"> <link rel="PREVIOUS" title="Signals" href="z109.html"> <link rel="NEXT" title="Attaching Data to Objects" href= "sec-objectdata.html"> </head> <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink= "#840084" alink="#0000FF"> <div class="NAVHEADER"> <table width="100%" border="0" bgcolor="#ffffff" cellpadding= "1" cellspacing="0"> <tr> <th colspan="4" align="center"> <font color="#000000" size="2">GTK+ / Gnome Application Development</font> </th> </tr> <tr> <td width="25%" bgcolor="#ffffff" align="left"> <a href="z109.html"><font color="#0000ff" size="2"><b> <<< Previous</b></font></a> </td> <td width="25%" colspan="2" bgcolor="#ffffff" align= "center"> <font color="#0000ff" size="2"><b><a href="ggad.html"> <font color="#0000ff" size="2"><b> Home</b></font></a></b></font> </td> <td width="25%" bgcolor="#ffffff" align="right"> <a href="sec-objectdata.html"><font color="#0000ff" size="2"><b>Next >>></b></font></a> </td> </tr> </table> </div> <div class="SECT1"> <h1 class="SECT1"> <a name="SEC-FINALIZATION">Object Finalization</a> </h1> <p> To write a <span class="STRUCTNAME">GtkObject</span>, you must implement the methods provided by the <span class= "STRUCTNAME">GtkObject</span> interface, or at least be sure you are happy with the default implementations. There are only five <span class="STRUCTNAME">GtkObject</span> methods; two of them are <span class="STRUCTNAME"> get_arg</span> and <span class="STRUCTNAME">set_arg</span>, described in <a href="hc-objectargs.html#SEC-GETSETARG">the section called <i>Using Object Arguments in Your Own <span class="STRUCTNAME">GtkObject</span> Subclass</i></a>. The other three implement object destruction; here are the fields in <span class="STRUCTNAME">GtkObjectClass</span>: </p> <table border="0" bgcolor="#E0E0E0" width="100%"> <tr> <td><pre class="PROGRAMLISTING"> void (* shutdown) (GtkObject *object); void (* destroy) (GtkObject *object); void (* finalize) (GtkObject *object); </pre> </td> </tr> </table> <p> As you might guess from this, objects are destroyed in a three-stage process. Each method represents one stage in the process; if your object subclass overrides any of them, it must "chain up" to the corresponding method in the parent class (see <a href= "sec-finalization.html#SEC-CHAINUP">the section called <i> Chaining Up</i></a>). The three methods do the following: </p> <ul> <li> <p> The <span class="STRUCTNAME">shutdown</span> method allows objects to perform actions before destruction begins. Most subclasses do not override this method; the default <span class="STRUCTNAME">shutdown</span> method emits the <span class="SYMBOL">"destroy"</span> signal to start the next phase. (The default implementation will <i class="EMPHASIS">always</i> be invoked, even if overridden, because subclasses are required to "chain up.") </p> </li> <li> <p> The <span class="STRUCTNAME">destroy</span> method marks the object "useless" and cleans up associated resources, but does not free the object itself. Typically a destroy method would free data, strings, and so on stored in the instance struct, and set the struct members to <span class="STRUCTNAME">NULL</span>. This is the method most subclasses override. </p> </li> <li> <p> The <span class="STRUCTNAME">finalize</span> method is invoked <i class="EMPHASIS">only when the object's reference count reaches 0</i>. The default implementation frees the object instance struct, so that further attempts to use the object result in a segmentation fault. The <span class="STRUCTNAME"> finalize</span> method must also consider that user code could have been invoked after the <span class= "STRUCTNAME">destroy</span> method, and free any data that user code could have allocated. </p> </li> </ul> <p> Note: <i class="EMPHASIS">Objects can be destroyed regardless of their reference count</i>. This means that the <span class="STRUCTNAME">shutdown</span> method is invoked and the <span class="STRUCTNAME">destroy</span> signal is emitted. However, as long as the reference count is greater than 0, the object will not be <i class= "EMPHASIS">finalized</i>. </p> <p> The <span class="STRUCTNAME">shutdown</span> method has no defined role; its purpose depends on the particular object. For example, the <tt class="CLASSNAME">GtkWidget</tt> shutdown implementation removes the widget from its parent container, and unrealizes the widget. This is especially important for containers: their <span class="STRUCTNAME"> destroy</span> method destroys all children of the container. If the container was not unrealized before destruction, it would still be visible and the user would see each child disappear, followed by the container. With the <span class="STRUCTNAME">shutdown</span> method, everything disappears at once. </p> <p> The <span class="STRUCTNAME">destroy</span> method frees as many resources as possible without rendering the object "unsafe." If your object has invariants describing its integrity, a <span class="STRUCTNAME">destroy</span> method will not violate them. All public functions exported by an object implementation should gracefully handle destroyed objects (they should not crash---remember that an object can be destroyed while references to it persist). The <span class="STRUCTNAME">finalize</span> method actually frees the object, meaning that attempts to use the object become dangerous bugs. </p> <p> The statement that "public functions exported by an object implementation should gracefully handle destroyed objects" requires some qualification. This is the intended behavior; otherwise, code could not ensure the sanity of an object by increasing its reference count. However, the implementation does not yet live up to the guarantee in all cases. Some public functions in GTK+ and Gnome still assume data structures freed in the destroy method exist, or re-allocate data structures the destroy method already freed. Unless the finalize method re-frees those data structures, they will be leaked. To avoid these bugs, it is best to avoid calling functions on destroyed objects (in practice, it would be uncommon to do so). </p> <p> You <i class="EMPHASIS">can</i> count on being able to check the type and object flags of a destroyed object, however; and it is certainly safe to call <tt class= "FUNCTION">gtk_object_unref()</tt> on a destroyed object. In your own object implementations, be sure you implement each public function correctly; check whether the object is destroyed with <tt class="FUNCTION"> GTK_OBJECT_DESTROYED()</tt>, and keep in mind that user code can run between the <span class="STRUCTNAME"> destroy</span> method and the <span class="STRUCTNAME"> finalize</span> method. </p> <p> Notice that the <span class="STRUCTNAME">destroy</span> method is the default handler for a <span class="SYMBOL"> "destroy"</span> signal, but the <span class="STRUCTNAME"> shutdown</span> and <span class="STRUCTNAME"> finalize</span> methods are class functions only. This reduces the complexity and increases the speed of the finalization process. Also, because <span class= "STRUCTNAME">finalize</span> destroys the integrity of an object, it would be unsafe to emit as a signal (GTK+ does have a facility called "weak references" that allows you to invoke a callback when an object is finalized---weak references do not assume that the <span class="STRUCTNAME"> GtkObject</span> is in a sane state). </p> <p> To make things more concrete, let's look at the functions you would use to destroy an object. First, <tt class= "FUNCTION">gtk_object_destroy()</tt>: </p> <table border="0" bgcolor="#E0E0E0" width="100%"> <tr> <td><pre class="PROGRAMLISTING"> voidgtk_object_destroy (GtkObject *object){ g_return_if_fail (object != NULL); g_return_if_fail (GTK_IS_OBJECT (object)); g_return_if_fail (GTK_OBJECT_CONSTRUCTED (object)); if (!GTK_OBJECT_DESTROYED (object)) { gtk_object_ref (object); object->klass->shutdown (object); gtk_object_unref (object); }} </pre> </td> </tr> </table> <p> Notice that destroyed-but-not-finalized objects are flagged, and this flag can be checked with the <tt class= "FUNCTION">GTK_OBJECT_DESTROYED()</tt> macro. <tt class= "FUNCTION">gtk_object_destroy()</tt> ensures that objects are not destroyed twice by ignoring any already-destroyed objects. If an object has not been destroyed, <tt class= "FUNCTION">gtk_object_destroy()</tt> references it to prevent finalization during the destroy process and invokes the shutdown method; by default, that method looks like this: </p> <table border="0" bgcolor="#E0E0E0" width="100%"> <tr> <td><pre class="PROGRAMLISTING"> static voidgtk_object_shutdown (GtkObject *object){ GTK_OBJECT_SET_FLAGS (object, GTK_DESTROYED); gtk_signal_emit (object, object_signals[DESTROY]);} </pre> </td> </tr> </table> <p> This method sets the destroyed flag, to ensure that any recursive <tt class="FUNCTION">gtk_object_destroy()</tt> calls have no effect; then it emits the <span class= "SYMBOL">"destroy"</span> signal. <tt class="FUNCTION"> gtk_object_shutdown()</tt> seems pointless by itself; however, subclasses may override this method with something more substantial, chaining up to the <span class= "STRUCTNAME">GtkObject</span> default method (see <a href= "sec-finalization.html#SEC-CHAINUP">the section called <i> Chaining Up</i></a>). </p> <p> It may be unclear that <tt class="FUNCTION"> gtk_object_shutdown()</tt> is a method implementation, while <tt class="FUNCTION">gtk_object_destroy()</tt> is a public function. Note that <tt class="FUNCTION"> gtk_object_shutdown()</tt> is the internal function that implements the <span class="STRUCTNAME">shutdown</span> method for the <span class="STRUCTNAME">GtkObject</span> class, while <tt class="FUNCTION">gtk_object_destroy()</tt>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -