1

次のように、未定義の引数を使用して関数を呼び出すプログラムがあります。

#include <stdargs.h>
... /* code */ int main () {
GArray *garray = g_array_new (FALSE, FALSE, sizeof (char *)); /* the code above initialize the GArray, and say that the garray expect a pointer to char. */
function_name (garray, "arg2", "arg3" /* and so on ... */);
... /* code */ }

「」の間の引数は文字列であるため、function_nameでは次のようになります。

static void function_name (GArray *garray, ...) {
  ... /* code */
  char *data;
data = va_arg (garray, gchar *); g_array_append_val (garray, data);
... /* code */ }

   したがって、データがva_listの引数を指している場合、関数が戻ると、データが指し示しているのは理論的には無効になり、garrayでも同様になります。
(データポインタが、予約されていないメモリアドレスを指しているため、参照がぶら下がっています)。

   しかし、それは起こらないようで、プログラムはうまく動作します。なぜ?そして、Cでは、関数に渡される引数はスタックに格納されるので、データポイントはスタック内で実際にメモリに存在しますか?

thnkxたくさん。

4

2 に答える 2

5

Cプログラムに文字列定数を導入すると、静的ストレージ期間を持つ名前のない、変更できないオブジェクトが作成されます。「静的保存期間」とは、プログラムの存続期間中有効であることを意味します。

したがって、コードにこれがある場合:

function_name (garray, "arg2", "arg3" /* and so on ... */);

文字列「arg2」と「arg3」は文字列定数です。これらは、プログラムの存続期間中、プログラムメモリのどこかに存在します。多くの場合、これらはプログラムコード自体と同じように、テキストセグメントに格納されます。

function_name()に実際に渡されるのは(おそらくスタック上で)、これらの文字列定数へのポインターです。そして、それがあなたのGArrayが最終的に格納するものです-それらの文字列定数へのポインタ。

(配列初期化子として使用される文字列は文字列定数ではないことに注意してください)。

于 2009-08-05T05:01:46.077 に答える
0

次の3つのうちの1つが当てはまります。

1)g_array_append_valは文字列のコピーを作成しています。

または:2)スタックが再び上書きされるとすぐに、問題が発生します。

void burn_stack(int size)
{
   char data[8]={0,0,0,0,0,0,0,0};
   size-=8;
   if (size>0) burn_stack(size);
}

burn_stack(256);を呼び出してみてください。function_nameの後に、物事が引き続き機能するかどうかを確認します。

または:3)const char "string"を使用しています。これは、実行可能ファイルの文字列セクションに格納されており、ヒープやスタックには格納されていないため、無期限に存続します。

于 2009-08-05T04:04:21.607 に答える