【问题标题】:Issues with C++ command-line arguments on WindowsWindows 上的 C++ 命令行参数问题
【发布时间】:2015-02-23 14:24:15
【问题描述】:

我在使用 C++ 解析 Windows 上的命令行参数时遇到了问题。 我试过用这个

int main(int argc, char **argv)
{
    std::cout << "Command-line argument count: " << argc << " \n";
    std::cout << "Arguments:\n";
    for (int i = 0; i < argc; i++)
        std::cout << "  argv[" << i << "]   "
        << argv[i] << "\n";

    return 0;
}

还有这个

int main(int argc, char *argv[])
{
    std::cout << "Command-line argument count: " << argc << " \n";
    std::cout << "Arguments:\n";
    for (int i = 0; i < argc; i++)
        std::cout << "  argv[" << i << "]   "
        << argv[i] << "\n";

    return 0;
}

变量argcargv 似乎以某种方式未初始化。 这就是启动程序返回给我的结果:

Z:\Dev\ProcessSuspender\Debug>ProcessSuspender a
Command-line argument count: 2130558976
Arguments:
  argv[0]
  argv[1]   ╠ÉÉÉÉÉj↑h╚♂YwÞØ÷■ âe³
  argv[2]

(崩溃跟随)

我使用 MSVC12 使用 /SUBSYSTEM:CONSOLE 链接器选项编译它。 这个问题的原因可能是什么?

【问题讨论】:

  • 你总是得到完全相同的垃圾数据吗?你能检查_mainCRTStartup 是否设置为入口点吗?您使用的是什么版本的 CRT?
  • 代码没有问题。检查您的项目设置。
  • @codefox 等一下,你是说手动将入口点设置为main?这行不通,入口点必须是 CRT 入口点mainCRTStartup,正如上面提到的 Rufflewind(好吧,据我所知,它是在链接器选项中指定的,没有前导下划线)。详情请看this question
  • @codefox 这适用于所有应用程序。需要一些代码来解析操作系统给出的命令行并构建main 的标准声明所需的参数。更不用说在调用 main 之前需要发生的所有其他事情。
  • @codefox /SUBSYSTEM:CONSOLE/SUBSYSTEM:WINDOWS 之间的一个区别是,当指定前者时,默认入口点是mainCRTStartup,所以你不需要明确地将其提供给链接器。

标签: c++ windows command-line-arguments msvc12


【解决方案1】:

我已手动将入口点设置为main。无论我是否使用默认项目设置 (_tmain),问题仍然存在。

一般来说,除非您知道后果,否则您不应该这样做。 entry point (/ENTRY) 的典型值应该是:

  • [w]mainCRTStartup,它调用[w]main,或者
  • [w]WinMainCRTStartup,它调用[w]WinMain,或者
  • _DllMainCRTStartup,它调用DllMain

为什么需要这个?嗯,…CRTStartup-family 函数do a couple crucial things,包括初始化:

  • C 运行时 (CRT),
  • 任何全局变量,以及
  • 参数argcargv,你不小心发现了。

所以对于一个典型程序,您可能希望它完成它的工作。在 Linux 世界中,有一个称为 _start 的等效函数也需要执行相同的初始化任务,可以在链接时用 -e 覆盖。

这里的混淆可能源于“入口点”一词的歧义含义不同:从语言的角度(即main及其同类)来看,存在“明显入口点”的含义,而从语言实现的角度来看“真正的入口点”的含义(即…CRTStartup_start)。

请注意,使用…CRTStartup 函数并非绝对必要,因为您当然可以编写一个避免使用它们的程序。然而,它确实是有代价的:

  • 你不能使用 C 运行时,所以你不能使用大部分标准库,
  • 您需要手动初始化所​​有全局变量,并且
  • 您需要使用Windows API(GetCommandLineWCommandLineToArgvW)手动获取argcargv

有些人这样做是为了避免对 CRT 的依赖,或最小化可执行文件的大小。

【讨论】:

  • 感谢详细的解释!今后,我一定会牢记这一点。这个问题真的让我发疯了,但现在一切正常。
  • 除非损坏,否则不要修复它!
【解决方案2】:

我在 VS 2012 上尝试了您的项目,并且运行顺利。 我添加了一个 getchar();命令如下:

#include <iostream>

int main(int argc, char *argv[])
{
    std::cout << "Command-line argument count: " << argc << " \n";
    std::cout << "Arguments:\n";
    for (int i = 0; i < argc; i++)
        std::cout << "  argv[" << i << "]   "
        << argv[i] << "\n";
    getchar();
    return 0;
}

这样我就可以看到输出了。

右击项目->属性->调试->命令 参数。

这在我的项目中是空的,我添加了字符 a 来模拟您的问题。

这是我得到的输出:

右键项目->调试->启动新实例->你会 喜欢建造它 -> 是的

输出:

Command-line argument count: 2
Arguments:
  argv[0]   <my macines path>\helpingStack1.exe
  argv[1]   a

请再次检查。我希望这会有所帮助。

1) 我怀疑在您运行此脚本时您的二进制文件不是最新的,因此请进行干净的构建并确认您确实在运行与您正在构建的那个相同的 exe。请检查配置 - 调试/发布。

2) 转到您创建项目的文件夹并右键单击项目文件夹,然后更改属性 -> 确保未选中复选框。

【讨论】:

  • 我创建了一个新项目来检查它是否是由某些项目设置引起的,但我仍然无法让它工作。 a.pomf.se/zfzngu.webm
  • 在 VS 2013 中也适用于我。检查是否有其他干扰,例如病毒扫描程序。
  • 我的开发机器上没有运行病毒扫描程序之类的东西。不应该有任何东西干扰任何东西。
【解决方案3】:

显然,IDE 或项目有问题,或者可能只是您系统上的任何其他设置有问题。 代码很完美。

您是否尝试过通过命令提示符直接独立运行您的输出 exe??

通过提供一些任意参数在命令提示符下运行您的 exe,并检查输出。

【讨论】:

  • 我都尝试了,从 IDE 和命令提示符运行它。结果是一样的。稍后我可能会尝试重新安装 VS,尽管其他一切都运行良好..
  • 它很奇怪......我想知道问题可能是什么......但是,作为一个盲目的镜头,我建议尝试使用另一个编译器,例如MinGW.... 祝你好运
【解决方案4】:

值得在项目属性->常规中检查您的字符集。

【讨论】:

  • 无论我将其设置为 Unicode 还是多字节都没有关系,在这两种情况下问题仍然存在。
猜你喜欢
  • 2016-04-22
  • 2015-10-17
  • 2011-02-12
  • 2012-05-12
  • 1970-01-01
相关资源
最近更新 更多