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 */ }

请注意,“”之间的 args 是字符串,因此,在 function_name 中:

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

   因此,如果 data 指向 va_list 中的参数,则当函数返回时,从理论上讲,指向的数据将变为无效,并且在 garray 中也是如此。
(导致悬空引用,因为数据指针指向未保留更多的内存地址)。

   但它似乎没有发生,程序运行良好。为什么?并且,在 C 中,传递给函数的参数存储在堆栈中,那么,堆栈中的数据点确实是内存吗?

非常感谢。

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

以下三件事之一是正确的:

要么: 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"s,它们存储在可执行文件的字符串部分中,而不是在堆或堆栈上,因此它们将无限期地存在。

于 2009-08-05T04:04:21.607 回答