?? cha-glib.html
字號:
</tr> </table> <p> <code><code class="FUNCDEF"><tt class="FUNCTION"> GINT_TO_POINTER</tt></code>(<tt class= "PARAMETER"><i>p</i></tt>);</code> </p> <p> <code><code class="FUNCDEF"><tt class="FUNCTION"> GPOINTER_TO_INT</tt></code>(<tt class= "PARAMETER"><i>p</i></tt>);</code> </p> <p> <code><code class="FUNCDEF"><tt class="FUNCTION"> GUINT_TO_POINTER</tt></code>(<tt class= "PARAMETER"><i>p</i></tt>);</code> </p> <p> <code><code class="FUNCDEF"><tt class="FUNCTION"> GPOINTER_TO_UINT</tt></code>(<tt class= "PARAMETER"><i>p</i></tt>);</code> </p> </div> <p> <b>Figure 2. Macros for storing integers in pointers</b> </p> </div> </div> <div class="SECT2"> <h2 class="SECT2"> <a name="Z27">Debugging Macros</a> </h2> <p> glib has a nice set of macros you can use to enforce invariants and preconditions in your code. GTK+ uses these liberally---one of the reasons it's so stable and easy to use. They all disappear when you define <tt class="FUNCTION">G_DISABLE_CHECKS</tt> or <tt class= "FUNCTION">G_DISABLE_ASSERT</tt>, so there's no performance penalty in production code. Using these liberally is a very, very good idea. You'll find bugs much faster if you do. You can even add assertions and checks whenever you find a bug to be sure the bug doesn't reappear in future versions---this complements a regression suite. Checks are especially useful when the code you're writing will be used as a black box by other programmers; users will immediately know when and how they've misused your code. </p> <p> Of course you should be very careful to ensure your code isn't subtly dependent on debug-only statements to function correctly. Statements that will disappear in production code should <i class="EMPHASIS">never</i> have side effects. </p> <div class="FIGURE"> <a name="ML-PRECONDITION"></a> <div class="FUNCSYNOPSIS"> <a name="ML-PRECONDITION.SYNOPSIS"></a> <table border="0" bgcolor="#E0E0E0" width="100%"> <tr> <td><pre class="FUNCSYNOPSISINFO">#include <glib.h></pre> </td> </tr> </table> <p> <code><code class="FUNCDEF"><tt class="FUNCTION"> g_return_if_fail</tt></code>(<tt class= "PARAMETER"><i>condition</i></tt>);</code> </p> <p> <code><code class="FUNCDEF"><tt class="FUNCTION"> g_return_val_if_fail</tt></code>(<tt class= "PARAMETER"><i>condition</i></tt>, <tt class= "PARAMETER"><i>retval</i></tt>);</code> </p> </div> <p> <b>Figure 3. Precondition Checks</b> </p> </div> <p> <a href="cha-glib.html#ML-PRECONDITION">Figure 3</a> shows glib's precondition checks. <tt class="FUNCTION"> g_return_if_fail()</tt> prints a warning and immediately returns from the current function if <span class="STRUCTNAME">condition</span> is <span class= "STRUCTNAME">FALSE</span>. <tt class="FUNCTION"> g_return_val_if_fail()</tt> is similar but allows you to return some <span class="STRUCTNAME">retval</span>. These macros are incredibly useful---if you use them liberally, especially in combination with GTK+'s runtime type checking, you'll halve the time you spend looking for bad pointers and type errors. </p> <p> Using these functions is simple; here's an example from the glib hash table implementation: </p> <table border="0" bgcolor="#E0E0E0" width="100%"> <tr> <td><pre class="PROGRAMLISTING"> voidg_hash_table_foreach (GHashTable *hash_table, GHFunc func, gpointer user_data){ GHashNode *node; gint i; g_return_if_fail (hash_table != NULL); g_return_if_fail (func != NULL); for (i = 0; i < hash_table->size; i++) for (node = hash_table->nodes[i]; node; node = node->next) (* func) (node->key, node->value, user_data);} </pre> </td> </tr> </table> <p> Without the checks, passing <span class="STRUCTNAME"> NULL</span> as a parameter to this function would result in a mysterious segmentation fault. The person using the library would have to figure out where the error occurred with a debugger, and maybe even dig in to the glib code to see what was wrong. With the checks, they'll get a nice error message telling them that <span class="STRUCTNAME">NULL</span> arguments are not allowed. </p> <div class="FIGURE"> <a name="ML-ASSERTIONS"></a> <div class="FUNCSYNOPSIS"> <a name="ML-ASSERTIONS.SYNOPSIS"></a> <table border="0" bgcolor="#E0E0E0" width="100%"> <tr> <td><pre class="FUNCSYNOPSISINFO">#include <glib.h></pre> </td> </tr> </table> <p> <code><code class="FUNCDEF"><tt class="FUNCTION"> g_assert</tt></code>(<tt class= "PARAMETER"><i>condition</i></tt>);</code> </p> <p> <code><code class="FUNCDEF"><tt class="FUNCTION"> g_assert_not_reached</tt></code>(void);</code> </p> </div> <p> <b>Figure 4. Assertions</b> </p> </div> <p> glib also has more traditional assertion macros, shown in <a href="cha-glib.html#ML-ASSERTIONS">Figure 4</a>. <tt class="FUNCTION">g_assert()</tt> is basically identical to <tt class="FUNCTION">assert()</tt>, but responds to <span class="STRUCTNAME"> G_DISABLE_ASSERT</span> and behaves consistently across all platforms. <tt class="FUNCTION"> g_assert_not_reached()</tt> is also provided; this is an assertion which always fails. Assertions call <tt class="FUNCTION">abort()</tt> to exit the program and (if your environment supports it) dump a core file for debugging purposes. </p> <p> Fatal assertions should be used to check <i class= "EMPHASIS">internal consistency</i> of a function or library, while <tt class="FUNCTION"> g_return_if_fail()</tt> is intended to ensure sane values are passed to the public interfaces of a program module. That is, if an assertion fails, you typically look for a bug in the module containing the assertion; if a <tt class="FUNCTION">g_return_if_fail()</tt> check fails, you typically look for the bug in the code which invokes the module. </p> <p> This code from glib's calendrical calculations module shows the difference: </p> <table border="0" bgcolor="#E0E0E0" width="100%"> <tr> <td><pre class="PROGRAMLISTING"> GDate*g_date_new_dmy (GDateDay day, GDateMonth m, GDateYear y){ GDate *d; g_return_val_if_fail (g_date_valid_dmy (day, m, y), NULL); d = g_new (GDate, 1); d->julian = FALSE; d->dmy = TRUE; d->month = m; d->day = day; d->year = y; g_assert (g_date_valid (d)); return d;} </pre> </td> </tr> </table> <p> The precondition check at the beginning ensures the user passes in reasonable values for the day, month and year; the assertion at the end ensures that glib constructed a sane object, given sane values. </p> <p> <tt class="FUNCTION">g_assert_not_reached()</tt> should be used to mark "impossible" situations; a common use is to detect switch statements that don't handle all possible values of an enumeration: </p> <table border="0" bgcolor="#E0E0E0" width="100%"> <tr> <td><pre class="PROGRAMLISTING"> switch (val) { case FOO_ONE: break; case FOO_TWO: break; default: /* Invalid enumeration value */ g_assert_not_reached(); break; } </pre> </td> </tr> </table> <p> All of the debugging macros print a warning using glib's <tt class="FUNCTION">g_log()</tt> facility, which means the warning includes the name of the originating application or library, and you can optionally install a replacement warning-printing routine. For example, you might send all warnings to a dialog box or log file instead of printing them on the console. </p> </div> <div class="SECT2"> <h2 class="SECT2"> <a name="GLIB-MEMORY">Memory</a> </h2> <p> glib wraps the standard <tt class="FUNCTION"> malloc()</tt> and <tt class="FUNCTION">free()</tt> with its own <span class="STRUCTNAME">g_</span> variants, <tt class="FUNCTION">g_malloc()</tt> and <tt class= "FUNCTION">g_free()</tt>, shown in <a href= "cha-glib.html#FL-MEMORY">Figure 5</a>. These are nice in several small ways: </p> <ul> <li> <p> <tt class="FUNCTION">g_malloc()</tt> always returns a <span class="STRUCTNAME">gpointer</span>, never a <span class="STRUCTNAME">char*</span>, so there's no need to cast the return value. </p> </li> <li> <p> <tt class="FUNCTION">g_malloc()</tt> aborts the program if the underlying <tt class="FUNCTION"> malloc()</tt> fails, so you don't have to check for a <span class="STRUCTNAME">NULL</span> return value. </p> </li> <li> <p> <tt class="FUNCTION">g_malloc()</tt> gracefully handles a <span class="STRUCTNAME">size</span> of <span class="STRUCTNAME">0</span>, by returning <span class="STRUCTNAME">NULL</span>.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -