【问题标题】:Unsymmetry between main and launching process主进程和启动进程之间的不对称
【发布时间】:2018-10-05 12:34:42
【问题描述】:

C 主方法有签名

int main(int argc, char** argv) {
}

它将获得一个命令行参数数组。但是当尝试启动应用程序时,例如使用CreateProcess 或ShellExecute,它们只接受2 个参数,一个用于启动应用程序,一个用于参数。 为什么不将参数也指定为数组? 为什么每个使用其他应用程序的应用程序都必须处理命令行参数的转义,例如,在调用具有 2 个可能包含的任意文件名的比较工具时空格还是引号?

【问题讨论】:

  • 您命名的示例函数使用 shell 执行。看看execv() 和朋友。
  • 不妨问问为什么太阳从东方升起。
  • 为什么不将参数也指定为数组? 但为什么必须?命令行作为单个字符串最原生的选项。 exe的入口点有ULONG __stdcall ep(PEB*)签名。 main 不是入口点
  • 您将 C 标准与 Windows API 进行比较。这些没有可比性。这个问题有点不合逻辑。

标签: c winapi main


【解决方案1】:

在极少数系统上,实际的程序执行实际上是从main(或WinMain)或类似函数开始的。相反,编译器告诉链接器使用一个特殊函数,该函数通常不会真正接受 any 参数,在 C 的意义上。

命令行参数(如果 any)可以通过汇编级别的特殊寄存器传递,或者需要使用特定于操作系统的特殊函数(如 Windows 中的 GetCommandLine API)。

在 Windows 上,GetCommandLine 函数确实将命令行作为单个字符串获取。就像它被传递给例如CreateProcess.

对于 Windows 控制台程序,特殊的“入口”函数会进行一些其他初始化(如设置 stdin 等),然后调用 GetCommandLine 以获取命令行参数,然后将其解析为适合main 函数的数组,然后调用该函数。


如果您查看 POSIX 世界(例如 Linux 和 macOS 所在的地方),那么他们有 the exec family of functions 确实需要一个数组作为参数。或者解析成这样一个数组的变量参数列表。

【讨论】:

  • “在 Windows 中,所有程序实际上都是从 WinMain 函数开始的。” - 这并不完全正确。所有 Windows 应用程序的入口点是 DWORD EntryPoint()。编译器运行时支持库执行其初始化,并分派到正确的用户提供的入口点。使用默认设置和 Microsoft 编译器,在定位 CONSOLE 子系统时没有 WinMain。
  • @IInspectable 改写答案,相当可观。
  • @IInspectable - 是的,一般来说这是真的,但如果想要 100% 准确 - exe 入口点的签名是 DWORD __stdcall EntryPoint(PEB*) 但如果我们使用 DWORD EntryPoint() - 这也可以没有问题
  • 相反,编译器告诉链接器使用特殊函数 - 不,通常编译器(比如 cl.exe)没有告诉链接器入口点//ENTRY 这是链接器,而不是编译器选项。我们直接告诉链接器入口点(不是通过编译器)或链接器默认根据子系统选择它
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-02
  • 2015-08-29
  • 2015-09-20
  • 1970-01-01
  • 1970-01-01
  • 2023-02-02
  • 2012-08-05
相关资源
最近更新 更多