【问题标题】:Where does argc come from?argc 是从哪里来的?
【发布时间】:2012-01-21 14:52:56
【问题描述】:

fork/exec 创建了一个新进程。 Exec 设置了命令行参数,但我没有看到它设置了要放入 argc 的这些参数的数量。

main() 应该是在新进程中运行的第一个函数,但此时 argc 已经设置好了。

在哪里设置?它必须是某种设置代码,在调用 main 之前计算参数,但我读过的任何内容都没有解释此设置代码的用途或它所在的位置。

这是libc 吗?这在每个操作系统上是否都相同并被某些规范所涵盖?除此之外,我在哪里可以找到设置代码中发生的事情?它是在实例化全局变量之前调用的吗?

【问题讨论】:

  • 您对哪种语言感兴趣?
  • 语言规范详细说明了 main 执行时的内容。阅读它们以找出答案。操作系统所做的事情和语言运行时所做的事情因实现而异。很难说更多,因为你的问题有点模糊。这是一个相当大的主题,而且非常具体。
  • 这非常依赖于系统。例如Linux 在内核的 execve 系统调用(do_execve() 函数)中计算 argv 中的项目。

标签: c++ c linux unix process


【解决方案1】:

在调用main 之前,在大多数实现中都会发生很多事情(通常是由类似于crt0 的东西设置的环境,C 运行时启动)。

main 退出后可能会发生很多事情,例如资源关闭、atexit 退出处理程序等等。

C 标准仅真正涵盖在语言方面发生的事情,而不是实现如何在幕后工作(这基本上就是您要问的)。每种实现都可能以不同的方式做事,但许多 UNIX 类型将具有类似于前面提到的 crt0 的东西,它负责设置。

【讨论】:

  • 因此,当您尝试编译没有 main() 的可执行文件时会出现 crt0 链接错误。有趣的是,这似乎处于操作系统规范和语言规范之间的无人区。优秀的!谢谢。
  • @sean 一点都不好笑。所有系统都以不同的方式处理进程。这些标准提供了一个通用接口。自然地,该语言的每个实现都必须在操作系统进程启动和main() 的启动之间提供一个实现特定的桥梁。事实上,这正是规格的全部内容。查看带有 4 个参数的 Windows 程序的 main 函数。这种风格在 C 标准出现之前就已经存在,这就是为什么它不是符合标准的 main 函数。
  • @DavidHeffernan 我不确定 C,但在 C++ 中 main 符合标准。该标准要求实现提供至少无参数和两个参数版本,但明确允许其他风格,为此它建议额外参数应该出现在 argc/argv 之后,但甚至不需要。它确实要求返回类型为int,但无论如何。
【解决方案2】:

操作系统会处理它。毕竟,处理线程和进程的是操作系统。

【讨论】:

  • 不,这是语言运行时的工作。
  • @DavidHeffernan:嗯,我会说它依赖于平台。
  • @MatteoItalia “除此之外,我在哪里可以找到设置代码中发生的事情?它是在实例化全局变量之前调用的吗?”这必须取决于运行时。
【解决方案3】:

使用 fork 会导致在下一行代码继续。 Exec 函数族创建一个新的执行,这取决于您使用的函数的第二个参数可能是参数数组。

#include <unistd.h>


int ret;
char *cmd[] = { "ls", "-l", (char *)0 };
char *env[] = { "HOME=/usr/home", "LOGNAME=home", (char *)0 };
...
ret = execve ("/bin/ls", cmd, env);

【讨论】:

    【解决方案4】:

    在 C 和 C++ 中,main() 是从 mainCRTStartup() 或类似函数调用的,具体取决于您的构建工具。如果您中断调试器并检查调用堆栈,您应该能够找到源代码。

    【讨论】:

      猜你喜欢
      • 2021-07-01
      • 1970-01-01
      • 2012-10-20
      • 2018-02-26
      • 2014-02-28
      • 2016-07-23
      • 2019-02-07
      • 1970-01-01
      • 2020-07-31
      相关资源
      最近更新 更多