int main(int argc, char* argv[]) & int main(int argc, char** argv)

G

Guest

Hi,

I have a question. I created a simple executable program using Visual C++
from Visual Studio 6.0

This program is called from a script that passes in one argument.

Now, my question is:

1. When I use int main(int argc, char* argv[]) declaration, the argv usually
contains the data and some garbage at the end.

For example: a script calls this executable and passes in data => this-is-me
When it executes this C++ program, the argv contains => this-is-me@#

Where did the @# come from? and Why?

2. When I use main(int argc, char** argv) declaration, the argv is exactly
what the script passes it.

For example: a script calls this executable and passes in data => this-is-me
When it executes the C++ program, the argv contains exactly => this-is-me

So, what is the difference between these two declarations? Why does the
first one contains garbage characters?

Please help me to understand. I am fairly new at Visual C++.

Many Thanks
 
D

Doug Harrison [MVP]

Hi,

I have a question. I created a simple executable program using Visual C++
from Visual Studio 6.0

This program is called from a script that passes in one argument.

Now, my question is:

1. When I use int main(int argc, char* argv[]) declaration, the argv usually
contains the data and some garbage at the end.

For example: a script calls this executable and passes in data => this-is-me
When it executes this C++ program, the argv contains => this-is-me@#

Where did the @# come from? and Why?

2. When I use main(int argc, char** argv) declaration, the argv is exactly
what the script passes it.

I don't understand how that can be. For function parameter declarations,
and only function parameter declarations, char** and char*[] mean the same
thing, pointer-to-pointer to char. Similarly, and again, in only this
context, char* and char[] mean the same thing, which is pointer to char.
For example: a script calls this executable and passes in data => this-is-me
When it executes the C++ program, the argv contains exactly => this-is-me

So, what is the difference between these two declarations? Why does the
first one contains garbage characters?

There is no difference. So there necessarily is some other difference,
which could be a compiler bug, though I cannot recall ever hearing of a
compiler bug such as this. How are you determining what the strings
contain?
Please help me to understand. I am fairly new at Visual C++.

If you are a newcomer to C++, don't feel bad, because arrays and pointers
are not the same thing at all, even though the syntax sometimes disagrees,
all in the interest of helping you declare things the way the language
designer thought you'd use them. The C FAQ has a lot of good information on
the subject:

6. Arrays and Pointers
http://c-faq.com/aryptr/index.html
 
C

Cholo Lennon

How do you access the arguments in both cases? Can you show some code?
The correct way with char argv[] is:

int main(int argc, char argv[])
{
if (argc>1)
printf("1st program argument=%s\n", argv[1]);
else
printf("Program %s is running without arguments\n", argv[0]);
}
 
B

Bruno van Dooren [MVP VC++]

Thanks for all responses. I access the arguments for both cases using
argv[1]...argv[n]

Hi,
That could be the problem. indexing in arrays is 0 based. meaning the first
element has index 0, and the last element has index n-1.
if n is the size of your array, indexing should be done
argv[0]...argv[n-1]

--

Kind regards,
Bruno van Dooren
(e-mail address removed)
Remove only "_nos_pam"
 
T

Tamas Demjen

Vin said:
Thanks for all responses. I access the arguments for both cases using
argv[1]...argv[n]

But what's up with the @# and where did it come from?

If you address an item outside of the array's memory space, such things
are expected to happen. Nobody knows where it's coming from, that's just
the content of your memory -- garbage, or the content of other objects,
perhaps leftover by the operating system or the debugger. You have no
control over that. Once you address an invalid pointer, the consequences
are undefined and somewhat random.
It will only show up for char* argv[] and not for char** argv

As others have already stated it, there's no difference between those
two types when they are used in function arguments.

If you don't believe it, cut and paste these 2 definitions:
void f(char* argv[]) { }
void f(char** argv) { }

You'll get a compiler error, something like "body has already been
defined for 'f(char**)'". They violate the One Definition Rule, because
they're identical.
for char* argv[]: Another weird thing is that at times it will have this @#
and at other times it doesn't.

See, this just proves the random nature of this behavior. It doesn't
depend on whether the type is char*[] or char**, but on circumstances
beyond your control. Due to a programming error, you're exploiting
undefined behavior. I have no question in my mind that when you use that
array properly, it will return the correct value.

Tom
 
D

Doug Harrison [MVP]

Hi,

Thanks for all responses. I access the arguments for both cases using
argv[1]...argv[n]

But what's up with the @# and where did it come from?

It will only show up for char* argv[] and not for char** argv

for char* argv[]: Another weird thing is that at times it will have this @#
and at other times it doesn't. Also if I execute the program on another
computer it never show up all.

Any ideas?

If you're using argv[n] for n > argc, the result is undefined, which means
anything is possible. You can compile with /FAs and compare the assembly
code generated by the compiler, but if the only difference is char** vs.
char*[], I'd expect it to be the same. How are you determining what the
strings contain? Show the code.
 
G

Guest

Thanks for all responses. I access the arguments for both cases using
argv[1]...argv[n]

But what's up with the @# and where did it come from?

If you go beyond the boundaries of the array, you get undefined values.
I.e. argv[n] returns something, but whatever it is is not subject to logical
behavior. You just get whatever value happens to be after argv[n-1]

That value is then interprested as a char pointer. That pointer can point
anywhere, since is is not a real pointer.
When you try to use that pointer to read a string, the string function will
start at that pointer, and search until it finds a 0 that indicates the end
of the string.

If you are lucky, it will find a 0 and use a bogus string.
if you are unlucky, it will continue searching until it hits an inaccessible
addres, at which time you will get an access violation.

since this is undefined behavior, you cannot compare what happens on 2
different computers, or 2 different runs of the application.
Your result depends on whatever happens to be in argv[n] when you read it.
 
N

Nathan Mates

Thanks for all responses. I access the arguments for both cases using
argv[1]...argv[n]

C/C++ count arrays from 0, so that the array boundaries should be
argv[0] .. argv[n-1]. Also, C/C++ tends to treat array sizes as merely
suggestions, not hard limits. You can invite a lot of security
problems in your programs if you don't program defensively. C/C++
tends to give you all the tools you need to shoot yourself in the
foot-- and offers you a bigger bullet. This gives them a lot of power,
but if you can't handle that power properly, you might want to
consider another language.

Nathan Mates
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top