2

I'm somehow having issues parsing command-line arguments on Windows in C++. I tried using this

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;
}

as well as this

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;
}

The variables argc and argv seem to be somehow uninitialized. That's what launching the program returns to me:

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

(crash following)

I compiled it with MSVC12 using the /SUBSYSTEM:CONSOLE linker option. What could be the cause of this issue?

codefox
  • 31
  • 4
  • 1
    Do you always get the exact same garbage data? Can you check if `_mainCRTStartup` is set as the entry point? What version of CRT are you using? – Rufflewind Dec 26 '14 at 08:55
  • There is nothing wrong with the code. Check your project settings. – CroCo Dec 26 '14 at 08:59
  • @Rufflewind I've manually set the entry point to `main`. Whether I use the default project setting (`_tmain`) or not, the issue persists. The project is using the `/MDd` flag. After setting it to `/MTd`, the application crashes instantly on startup. I'll reinstall VS and everything else related to it, maybe there are some version conflicts. – codefox Dec 26 '14 at 09:17
  • 3
    @codefox Wait a second, did you say you manually set the entry point to `main`? That won't work, the entry point needs to be the CRT entry point, `mainCRTStartup`, as Rufflewind mentioned above (well, except it's specified in the linker options without the leading underscore as far as I know). Look at [this question](http://stackoverflow.com/questions/22934206/what-is-the-difference-between-main-and-maincrtstartup) for details. – bogdan Dec 26 '14 at 09:32
  • @bogdan Does this also apply to command-line applications? As far as I know, this only applies to WinAPI applications. Also, I only changed the entry point after noticing this issue. – codefox Dec 26 '14 at 09:42
  • 1
    @codefox This applies to all applications. There needs to be some code that parses the command line as given by the OS and builds the arguments needed by the standard declaration of `main`. Not to mention all the other stuff that needs to happen before `main` is called. – bogdan Dec 26 '14 at 09:44
  • @bogdan Thanks for pointing this out. Now it's working seemlessly. That's what happens when you switch from *nix development to Windows, I guess... – codefox Dec 26 '14 at 09:48
  • 1
    @codefox One difference between `/SUBSYSTEM:CONSOLE` and `/SUBSYSTEM:WINDOWS` is that when the former is specified the *default* entry point is `mainCRTStartup`, so you don't need to explicitly give it to the linker. – bogdan Dec 26 '14 at 09:51

4 Answers4

6

I've manually set the entry point to main. Whether I use the default project setting (_tmain) or not, the issue persists.

In general, you should not do that unless you know the consequences. The typical values of the entry point (/ENTRY) should be either:

  • [w]mainCRTStartup, which calls [w]main, or
  • [w]WinMainCRTStartup, which calls [w]WinMain, or
  • _DllMainCRTStartup, which calls DllMain.

Why is this needed? Well, the …CRTStartup-family of functions do a couple crucial things, including the initialization of:

  • the C runtime (CRT),
  • any global variables, and
  • the arguments argc and argv, as you've accidentally found out.

So for a typical program you probably want it to do its job. In the Linux world, there is an equivalent function called _start that is needed to do the same initialization tasks as well, which can be overridden with -e while linking.

The confusion here probably stems from difference in ambiguous meaning of the word "entry point": there is the meaning of "apparent entry point" from the perspective of the language (which is main and its ilk), and the meaning of the "true entry point" from the perspective of the language implementation (which is …CRTStartup or _start).

Note that using the …CRTStartup functions is not absolutely essential, as you can certainly write a program that avoids using them. It does come with a cost, however:

  • you can't use the C runtime, so you can't use most of the standard library,
  • you need to manually initialize any global variables, and
  • you need to manually obtain argc and argv using the Windows API (GetCommandLineW and CommandLineToArgvW).

Some do this to avoid dependency on the CRT, or to minimize the executable size.

Community
  • 1
  • 1
Rufflewind
  • 8,545
  • 2
  • 35
  • 55
  • Thanks for the detailed explanation! In the future, I'll surely keep this in mind. This issue was really driving me crazy, but now everything works just fine. – codefox Dec 26 '14 at 18:48
  • Don't fix it unless broken! – Ajay Dec 27 '14 at 07:07
1

I tried your project on VS 2012 and it is working smoothly. I added a getchar(); command as below:

#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;
}

so that i could see the output.

Right-click on Project -> Properties -> debugging -> Command Arguments.

This was empty in my project and i added the character a to simulate your problem.

Here is the output i am getting:

Right click on the project -> Debug -> Start new Instance -> would you like to build it -> yes

Output:

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

Please check this again. I hope this helps.

1) I am suspecting that your binaries are not up to date when you run this script so please do a clean build and verify that you are indeed running the same exe as the one you are building. Please check the configuration - Debug/Release.

2) go to the folder where you have created the project and righclick on the project folder, and change property -> ensure read only is not checked in the check box.

  • I created a new project to check whether it is caused by some project settings, but I could still not get it to work. http://a.pomf.se/zfzngu.webm – codefox Dec 26 '14 at 08:19
  • Works fine for me in VS 2013 as well. Check for something else interfering like a virus scanner. – Retired Ninja Dec 26 '14 at 08:31
  • I don't have anything like a virus scanner running on my development machine. There shouldn't be anything interfering with anything. – codefox Dec 26 '14 at 08:32
0

Obviously, Something is wrong with the IDE or project or maybe anything else's setup on your system only. The code is perfect.

Have you tried directly and independently running your output exe, by executing it through command prompt ??

Run your exe with command prompt by supplying some arbitrary arguments, and check the output.

AneesAhmed777
  • 2,475
  • 2
  • 13
  • 18
  • 1
    I tried both, running it from the IDE and the command prompt. The result is the same. I'll probably try reinstalling VS later, although everything else runs fine.. – codefox Dec 26 '14 at 09:10
  • 1
    Its strange..... I wonder what the problem might be..... However, as a blind shot, i suggest trying with another compiler, e.g. MinGW.... Gud luck – AneesAhmed777 Dec 26 '14 at 10:44
-1

its worth to check your character set in project properties->General.

GingerJack
  • 3,044
  • 1
  • 17
  • 19