Visual Studio C++ 2010 how can __argv be a null pointer?

2
int _tmain(int argc, _TCHAR* argv[])
{

    if (argc != 3) {
        printf("Format is straightline.exe <EO records file> <output file>");
        return 1;
    }
    string eoPath = string(__argv[1]);
    //...other stuff ...
}

If __argc == 3, how can __argv be a null pointer?

My debugger is telling me that __argv is pointing to 0x00000000 after the program crashed when I was trying to reference __argv[1] (and I have verified that __argc == 3). This is a minimal program and it happened in the beginning before I did any sort of processing.

visual-studio-2010
visual-c++
argv
asked on Stack Overflow Mar 16, 2012 by pete • edited May 19, 2015 by Chris Krycho

4 Answers

4

If this is complied as unicode, then __argv will be null, while __wargv will contain what you want. I believe that there is a __targv that should contain the command line arguments regardless of unicode or ascii.

But why use any of these if you can just use argv passed in as a parameter to _tmain?

answered on Stack Overflow Mar 16, 2012 by FriendlyGuy
2

The pointer to __argv can (and will) be null in Unicode configurations.

answered on Stack Overflow Mar 16, 2012 by Shocker • edited May 19, 2015 by Chris Krycho
1

__argc, __argv/__wargv and __envp/__wenvp are special globals used by the CRT init, you shouldn't ever touch these, rather just stick to the variables passed to your main/wmain/_tmain function, these are derived from the aforementioned globals, and they are guaranteed to be correct, and thanks to Microsofts macro's for the _tmain variant, they will also use the correct character encoding (UNICODE vs MBCS/ASCII).

answered on Stack Overflow Mar 16, 2012 by Necrolis • edited Mar 16, 2012 by Necrolis
0

Let us imagine we need to write cli_arguments().

Of course calling cli_arguments() might be happening anytime, including before and after main. Thus both __argv and __wargv might be nullptr. Also we do not know are we in the UNICODE app or not.

So why don't we just deliver them both for callers to choose from? And we will deliver them as std::vectors. Something like this:

auto [ wide_cl_args, narrow_cl_args   ] = dbj::cli_arguments();

    if (wide_cl_args.size())
        work_on_args(w_cli); 
    else
    if (narrow_cl_args.size())
        work_on_args(n_cli);
     else {
// CAUTION! They might be both empty at this time
} ;

Above will work in any kind of Windows APP, being called at any time. even before or after main(). The implementation is simple.

///
/// (c) 2020 by dbj.org, CC BY SA 4.0
struct cli_arguments_vectors final
{
    using wide_type = std::vector<wchar_t* >;
    using narrow_type = std::vector<char*  >;

    wide_type wide{};
    narrow_type narrow{};
};

inline cli_arguments_vectors cli_arguments()
{
    cli_arguments_vectors retval{};

    if (__wargv)
        retval.wide = cli_arguments_vectors::wide_type( __wargv, __wargv + argc_ );

    if (__argv)
        retval.narrow = cli_arguments_vectors::narrow_type( __argv, __argv + argc_ );

    return retval;
}
answered on Stack Overflow Feb 2, 2020 by Chef Gladiator

User contributions licensed under CC BY-SA 3.0