为什么主函数参数的地址每次都会改变?

时间:2010-11-17 14:47:53

标签: c parameters main memory-address

我写了一个打印argv [0]内容的测试 - 主函数参数的地址如下:

printf("%p\n",argv[0]);

我在Windows 7上使用Visual Studio 2008编译了程序。

然后我执行了1000次程序,将结果输出到文件中。结果,argv [0]的地址发生了变化,但是,有些地址是相同的,重复约10次。

为什么主函数参数的地址每次都会改变?

3 个答案:

答案 0 :(得分:2)

在二进制可执行文件的主例程开始之前,应将

argcargv置于堆栈中。实际上我认为argv是在堆内的某处动态分配的,然后指针放在堆栈上。

这意味着堆分配器是关心数据分配位置的那个,这就是它每次都改变的原因(它取决于策略)..你的程序会要求操作系统为参数分配空间(考虑通过malloc)所以可以根据某些事情做出内部选择(比如他们所说的ASLR)

答案 1 :(得分:1)

有趣的问题,我在程序自己的地址空间中看到很少或没有理由不确定。但我会告诉你我所知道的。

首先,不是通过windows而是通过stdc运行时分配,创建和初始化argv。反过来,这引发了另一个问题 - winmain的lpCmdLine参数是否也会发生变化?在同一个堆上分配了几个其他变量,可能还会复制环境变量。其中一个必须具有大小,具体取决于执行的实例。

无论如何,为什么黑盒子在琢磨?你的反汇编者,士兵在哪里?

答案 2 :(得分:0)

首先,这是语言标准(n1256)所说的内容:

5.1.2.2.1程序启动
...
2如果声明它们,主函数的参数应遵循以下内容 限制:

  • argc的值应为非负。

  • argv[argc]应为空指针。

  • 如果argc的值大于零,则数组成员argv[0]通过 argv[argc-1]包含应包含指向字符串的指针 程序启动前主机环境实现定义的值。该 意图是在程序启动之前为程序提供信息 来自托管环境中的其他地方。如果主机环境不具备 为字符串提供大写和小写的字母,实现 应确保琴弦以小写形式收到。

  • 如果argc的值大于零,则argv[0]指向的字符串 表示程序名称; argv[0][0]如果是,则为空字符 程序名称不能从主机环境中获得。如果argc的值是 大于一,argv[1]通过argv[argc-1]指向的字符串 代表程序参数

  • 参数argcargv以及argv数组指向的字符串应 可以由程序修改,并在程序之间保留它们最后存储的值 启动和程序终止。

关于的最后一个项目是最有趣的,其中存储了传递给main的字符串参数。它们必须是可修改的,并且必须具有静态范围,这对它们驻留在内存中的位置设置了一些限制。但是,每次运行程序时,语言定义部分都不要求它们位于同一位置。

我已经通过MSDN粗略搜索了一下,看看他们是否有任何明确的说法,但还没有找到任何内容。它可能归结为对OP的评论中提到的ASLR。