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.
If this is complied as unicode, then
will be null, while __argv
will contain what you want. I believe that there is a __wargv
that should contain the command line arguments regardless of unicode or ascii.__targv
But why use any of these if you can just use argv
passed in as a parameter to _tmain?
The pointer to __argv
can (and will) be null
in Unicode configurations.
__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).
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;
}
User contributions licensed under CC BY-SA 3.0