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

发布于 2024-10-03 11:15:35 字数 252 浏览 9 评论 0原文

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

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

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

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

为什么main函数的参数地址每次都会变化?

I write a test which print the content of argv[0]--the address of main function's parameter as followed:

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

I compiled the program with Visual Studio 2008 on Windows 7.

Then I executed the program 1000 times which output the results to a file. As a result, the address of argv[0] changes, however, some addresses are the same and repeat about 10 times.

Why the address of main function's parameter changes each time?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

娇俏 2024-10-10 11:15:35

有趣的问题,我认为程序自己的地址空间中的非确定性的原因很少或根本没有。但我会告诉你我所知道的。

首先,argv不是由windows而是由stdc运行时分配、创建和初始化的。这反过来又提出了另一个问题 - winmain 的 lpCmdLine 参数也会改变吗?在同一个堆上分配了几个其他变量,可能环境变量也被复制。其中之一的大小必须取决于执行实例。

无论如何,为什么要进行黑盒思考呢?你的反汇编器在哪里,士兵?

Interesting question, I see very few or no reasons for non-determinism of that in program's own address space. But I will tell you what I do know.

First, argv is allocated, created and initialized not by windows but by stdc runtime. Which, in turn, raises another question - does lpCmdLine parameter of winmain also change? There're several other variables allocated on the same heap, probably environment vars are also copied. One of them must have size depending on the instance of execution.

Anyway, why blackbox pondering? Where's your disassembler, soldier?

小梨窩很甜 2024-10-10 11:15:35

argcargv 应在二进制可执行文件的主例程开始之前放入堆栈。实际上我认为 argv 是在堆内的某个位置动态分配的,然后指针被放置到堆栈上。

这意味着堆分配器是关心数据分配位置的分配器,这就是它每次都会更改的原因(这取决于策略)..您的程序将要求操作系统为参数分配空间(考虑一下通过 malloc),因此可以根据某些内容做出内部选择(例如他们正在谈论的 ASLR)

argc and argv should be placed onto the stack before the begin of the main routine of the binary executable. Actually I think that argv is dynamically allocated somewhere inside the heap and then the pointer is placed onto the stack.

This means that the heap allocator is the one that cares about where the data is allocated and this is why it changes everytime (it depends on the policy).. your program will ask to the OS to allocate the space for the arguments (think about passing through malloc) so there can be internal choices made according to something (like the ASLR they were talking about)

最好是你 2024-10-10 11:15:35

首先,这是语言标准(n1256)必须说:

5.1.2.2.1 程序启动
...
2 如果声明了主函数的参数,则应遵守以下规定
限制条件:

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

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

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

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

我粗略地搜索了 MSDN,看看他们是否说了任何明确的内容,但还没有找到任何内容。正如OP评论中提到的那样,它可能归结为ASLR。

First of all, here's what the language standard (n1256) has to say:

5.1.2.2.1 Program startup
...
2 If they are declared, the parameters to the main function shall obey the following
constraints:

  • The value of argc shall be nonnegative.
  • argv[argc] shall be a null pointer.
  • If the value of argc is greater than zero, the array members argv[0] through
    argv[argc-1] inclusive shall contain pointers to strings, which are given
    implementation-defined values by the host environment prior to program startup. The
    intent is to supply to the program information determined prior to program startup
    from elsewhere in the hosted environment. If the host environment is not capable of
    supplying strings with letters in both uppercase and lowercase, the implementation
    shall ensure that the strings are received in lowercase.

  • If the value of argc is greater than zero, the string pointed to by argv[0]
    represents the program name; argv[0][0] shall be the null character if the
    program name is not available from the host environment. If the value of argc is
    greater than one, the strings pointed to by argv[1] through argv[argc-1]
    represent the program parameters.

  • The parameters argc and argv and the strings pointed to by the argv array shall
    be modifiable by the program, and retain their last-stored values between program
    startup and program termination.

The last bullet is the most interesting with respect to where the string arguments passed to main are stored. They must be modifiable and they must have static extent, which places some limits on where they reside in memory. There's no requirement on the part of the language definition that they reside in the same location every time the program is run, though.

I've done a cursory search through MSDN to see if they say anything explicit, but haven't found anything yet. It probably comes down to ASLR as mentioned in the comments to the OP.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文