我写了一个打印argv [0]内容的测试 - 主函数参数的地址如下:
printf("%p\n",argv[0]);
我在Windows 7上使用Visual Studio 2008编译了程序。
然后我执行了1000次程序,将结果输出到文件中。结果,argv [0]的地址发生了变化,但是,有些地址是相同的,重复约10次。
为什么主函数参数的地址每次都会改变?
答案 0 :(得分:2)
argc
和argv
置于堆栈中。实际上我认为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]
指向的字符串 代表程序参数。
- 参数
argc
和argv
以及argv
数组指向的字符串应 可以由程序修改,并在程序之间保留它们最后存储的值 启动和程序终止。
关于的最后一个项目是最有趣的,其中存储了传递给main
的字符串参数。它们必须是可修改的,并且必须具有静态范围,这对它们驻留在内存中的位置设置了一些限制。但是,每次运行程序时,语言定义部分都不要求它们位于同一位置。
我已经通过MSDN粗略搜索了一下,看看他们是否有任何明确的说法,但还没有找到任何内容。它可能归结为对OP的评论中提到的ASLR。