Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #69203 > unrolled thread
| Started by | m.labanowicz@gmail.com |
|---|---|
| First post | 2015-09-03 13:28 -0700 |
| Last post | 2015-09-04 20:48 +0200 |
| Articles | 8 — 5 participants |
Back to article view | Back to comp.lang.c
[clang] -Os invalid content of argc+argv m.labanowicz@gmail.com - 2015-09-03 13:28 -0700
Re: [clang] -Os invalid content of argc+argv Melzzzzz <mel@zzzzz.com> - 2015-09-03 23:31 +0200
Re: [clang] -Os invalid content of argc+argv Keith Thompson <kst-u@mib.org> - 2015-09-03 16:43 -0700
Re: [clang] -Os invalid content of argc+argv Melzzzzz <mel@zzzzz.com> - 2015-09-04 01:53 +0200
Re: [clang] -Os invalid content of argc+argv Philip Lantz <prl@canterey.us> - 2015-09-03 20:15 -0700
Re: [clang] -Os invalid content of argc+argv Keith Thompson <kst-u@mib.org> - 2015-09-04 09:15 -0700
Re: [clang] -Os invalid content of argc+argv m.labanowicz@gmail.com - 2015-09-04 10:33 -0700
Re: [clang] -Os invalid content of argc+argv Noob <root@127.0.0.1> - 2015-09-04 20:48 +0200
| From | m.labanowicz@gmail.com |
|---|---|
| Date | 2015-09-03 13:28 -0700 |
| Subject | [clang] -Os invalid content of argc+argv |
| Message-ID | <68a9e68b-dc3b-4c5e-8d01-bc91daaeb0f2@googlegroups.com> |
Hello,
I have found an unexpected result of application compiled with clang.
'argc' + 'argv' values are incorrect.
Main conditions where issue is observed:
a) compilation under system: Windows 10 + Cygwin64
(Ubuntu.14.04.64bit on the same machine issue is not observed)
b) enabled optimisation for size flag: -Os
c) clang or clang++ compilator
(not observed with gcc/g++)
Following is an example that demonstrates the issue:
--{example:beg}--------------------------------------
# gawk '{printf("/*%04d*/ %s\n", NR, $0);}' main.c
/*0001*/ #include <stdio.h>
/*0002*/ #include <stdlib.h>
/*0003*/ #ifdef __cplusplus
/*0004*/ extern "C" {
/*0005*/ #endif
/*0006*/ int bar(int argc, char * argv [])
/*0007*/ {
/*0008*/ printf("argc=%d, argv=%p\n", argc, (void *)(argv));
/*0009*/ if (argv) {
/*0010*/ int i = 0;
/*0011*/ while (argv[i]) {
/*0012*/ printf("argv[%d] = %p", i, (void *)(argv[i]));
/*0013*/ if (argv[i]) {
/*0014*/ printf(" = \"%s\"", argv[i]);
/*0015*/ }
/*0016*/ printf("\n");
/*0017*/ ++i;
/*0018*/ }
/*0019*/ }
/*0020*/ return EXIT_SUCCESS;
/*0021*/ }
/*0022*/ int main(int argc, char * argv [])
/*0023*/ {
/*0024*/ return bar(argc, argv);
/*0025*/ }
/*0026*/ #ifdef __cplusplus
/*0027*/ }
/*0028*/ #endif
# gcc --version && gcc -Os main.c -o a.exe && ./a.exe 1 2 3
gcc (GCC) 4.9.3
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
argc=4, argv=0x24cb50
argv[0] = 0x18032a770 = "./a"
argv[1] = 0x18032b7b8 = "1"
argv[2] = 0x18032b808 = "2"
argv[3] = 0x18032b7e0 = "3"
# g++ --version && g++ -Os main.c -o a.exe && ./a.exe 1 2 3
g++ (GCC) 4.9.3
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
argc=4, argv=0x24cb50
argv[0] = 0x18032a770 = "./a"
argv[1] = 0x18032b7b8 = "1"
argv[2] = 0x18032b808 = "2"
argv[3] = 0x18032b7e0 = "3"
# clang --version && clang -Os main.c -o a.exe && ./a.exe 1 2 3
clang version 3.5.2 (tags/RELEASE_352/final)
Target: x86_64-unknown-windows-cygnus
Thread model: posix
argc=1, argv=0x0
# clang++ --version && clang++ -Os main.c -o a.exe && ./a.exe 1 2 3
clang version 3.5.2 (tags/RELEASE_352/final)
Target: x86_64-unknown-windows-cygnus
Thread model: posix
clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated
argc=1, argv=0x0
--{example:eof}--------------------------------------
Is there any reasonable explanation of that ?
Regards
--
Maciek
[toc] | [next] | [standalone]
| From | Melzzzzz <mel@zzzzz.com> |
|---|---|
| Date | 2015-09-03 23:31 +0200 |
| Message-ID | <20150903233124.38258cdb@maxa-pc> |
| In reply to | #69203 |
On Thu, 3 Sep 2015 13:28:33 -0700 (PDT)
m.labanowicz@gmail.com wrote:
> Hello,
>
> I have found an unexpected result of application compiled with clang.
>
> 'argc' + 'argv' values are incorrect.
>
> Main conditions where issue is observed:
> a) compilation under system: Windows 10 + Cygwin64
> (Ubuntu.14.04.64bit on the same machine issue is not observed)
> b) enabled optimisation for size flag: -Os
> c) clang or clang++ compilator
> (not observed with gcc/g++)
>
> Following is an example that demonstrates the issue:
>
> --{example:beg}--------------------------------------
>
> # gawk '{printf("/*%04d*/ %s\n", NR, $0);}' main.c
> /*0001*/ #include <stdio.h>
> /*0002*/ #include <stdlib.h>
> /*0003*/ #ifdef __cplusplus
> /*0004*/ extern "C" {
> /*0005*/ #endif
> /*0006*/ int bar(int argc, char * argv [])
> /*0007*/ {
> /*0008*/ printf("argc=%d, argv=%p\n", argc, (void *)(argv));
> /*0009*/ if (argv) {
> /*0010*/ int i = 0;
> /*0011*/ while (argv[i]) {
> /*0012*/ printf("argv[%d] = %p", i, (void *)(argv[i]));
> /*0013*/ if (argv[i]) {
> /*0014*/ printf(" = \"%s\"", argv[i]);
> /*0015*/ }
> /*0016*/ printf("\n");
> /*0017*/ ++i;
> /*0018*/ }
> /*0019*/ }
> /*0020*/ return EXIT_SUCCESS;
> /*0021*/ }
> /*0022*/ int main(int argc, char * argv [])
> /*0023*/ {
> /*0024*/ return bar(argc, argv);
> /*0025*/ }
> /*0026*/ #ifdef __cplusplus
> /*0027*/ }
> /*0028*/ #endif
>
> # gcc --version && gcc -Os main.c -o a.exe && ./a.exe 1 2 3
> gcc (GCC) 4.9.3
> Copyright (C) 2015 Free Software Foundation, Inc.
> This is free software; see the source for copying conditions. There
> is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
> PARTICULAR PURPOSE.
>
> argc=4, argv=0x24cb50
> argv[0] = 0x18032a770 = "./a"
> argv[1] = 0x18032b7b8 = "1"
> argv[2] = 0x18032b808 = "2"
> argv[3] = 0x18032b7e0 = "3"
>
> # g++ --version && g++ -Os main.c -o a.exe && ./a.exe 1 2 3
> g++ (GCC) 4.9.3
> Copyright (C) 2015 Free Software Foundation, Inc.
> This is free software; see the source for copying conditions. There
> is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
> PARTICULAR PURPOSE.
>
> argc=4, argv=0x24cb50
> argv[0] = 0x18032a770 = "./a"
> argv[1] = 0x18032b7b8 = "1"
> argv[2] = 0x18032b808 = "2"
> argv[3] = 0x18032b7e0 = "3"
>
> # clang --version && clang -Os main.c -o a.exe && ./a.exe 1 2 3
> clang version 3.5.2 (tags/RELEASE_352/final)
> Target: x86_64-unknown-windows-cygnus
> Thread model: posix
> argc=1, argv=0x0
>
> # clang++ --version && clang++ -Os main.c -o a.exe && ./a.exe 1 2 3
> clang version 3.5.2 (tags/RELEASE_352/final)
> Target: x86_64-unknown-windows-cygnus
> Thread model: posix
> clang: warning: treating 'c' input as 'c++' when in C++ mode, this
> behavior is deprecated argc=1, argv=0x0
>
> --{example:eof}--------------------------------------
>
> Is there any reasonable explanation of that ?
I don't know about cygwin but argc/argv values are parsed with crt
on Linux. That is if you link with c runtime and write main in assembler
you get already parsed values eg Linux passes values on stack but crt
parses them into rdi,rsi registers...
Probably on cygwin compiler parses those values therefore bug.
>
> Regards
>
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-09-03 16:43 -0700 |
| Message-ID | <lnbndjqda9.fsf@kst-u.example.com> |
| In reply to | #69222 |
Melzzzzz <mel@zzzzz.com> writes:
[...]
> I don't know about cygwin but argc/argv values are parsed with crt
> on Linux. That is if you link with c runtime and write main in assembler
> you get already parsed values eg Linux passes values on stack but crt
> parses them into rdi,rsi registers...
> Probably on cygwin compiler parses those values therefore bug.
The command line is parsed by the shell, which then passes them to your
program using one of the exec*() functions.
The compiler doesn't parse your program's command line arguments
(because they don't exist yet). It merely generates code that is able
to receive those arguments via the argc and argv parameters.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Melzzzzz <mel@zzzzz.com> |
|---|---|
| Date | 2015-09-04 01:53 +0200 |
| Message-ID | <20150904015342.411a46af@maxa-pc> |
| In reply to | #69242 |
On Thu, 03 Sep 2015 16:43:58 -0700 Keith Thompson <kst-u@mib.org> wrote: > Melzzzzz <mel@zzzzz.com> writes: > [...] > > I don't know about cygwin but argc/argv values are parsed with crt > > on Linux. That is if you link with c runtime and write main in > > assembler you get already parsed values eg Linux passes values on > > stack but crt parses them into rdi,rsi registers... > > Probably on cygwin compiler parses those values therefore bug. > > The command line is parsed by the shell, which then passes them to > your program using one of the exec*() functions. > > The compiler doesn't parse your program's command line arguments > (because they don't exist yet). It merely generates code that is able > to receive those arguments via the argc and argv parameters. > Hm, when I don't link with crt, rather make assembly executable independently, I don;t have argc,argv parameters as function arguments at all, rather they are laid down on stack... at least on x86-64 Linux... Of course shell parses command line but what I actually meant is that crt parses stack and forms argc,argv as standard function parameters (rdi->argc (first function parameter),rsi->argv (second function parameter).
[toc] | [prev] | [next] | [standalone]
| From | Philip Lantz <prl@canterey.us> |
|---|---|
| Date | 2015-09-03 20:15 -0700 |
| Message-ID | <MPG.3052aca464f49aad5a@news.eternal-september.org> |
| In reply to | #69242 |
Keith Thompson wrote: > Melzzzzz writes: > > I don't know about cygwin but argc/argv values are parsed with crt > > on Linux. That is if you link with c runtime and write main in assembler > > you get already parsed values eg Linux passes values on stack but crt > > parses them into rdi,rsi registers... > > Probably on cygwin compiler parses those values therefore bug. > > The command line is parsed by the shell, which then passes them to your > program using one of the exec*() functions. > > The compiler doesn't parse your program's command line arguments > (because they don't exist yet). It merely generates code that is able > to receive those arguments via the argc and argv parameters. Actually, Melzzzzz is right, although I can see why his description was confusing. On Unix, execv doesn't create the values for argc and argv; it just passes to the program the strings needed to populate argv. The C runtime needs to interpret (or "parse") the strings received from the kernel and create the values for argc and argv. On Windows, the operating system passes the entire command line as a single string, so the C runtime does need to parse it (in the usual sense) as well as construct the argc and argv values. You're right that in neither case is it done by the compiler, per se, but the C runtime is part of the compiler package, not part of the operating system.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-09-04 09:15 -0700 |
| Message-ID | <ln4mjaqhyr.fsf@kst-u.example.com> |
| In reply to | #69250 |
Philip Lantz <prl@canterey.us> writes:
> Keith Thompson wrote:
>> Melzzzzz writes:
>> > I don't know about cygwin but argc/argv values are parsed with crt
>> > on Linux. That is if you link with c runtime and write main in assembler
>> > you get already parsed values eg Linux passes values on stack but crt
>> > parses them into rdi,rsi registers...
>> > Probably on cygwin compiler parses those values therefore bug.
>>
>> The command line is parsed by the shell, which then passes them to your
>> program using one of the exec*() functions.
>>
>> The compiler doesn't parse your program's command line arguments
>> (because they don't exist yet). It merely generates code that is able
>> to receive those arguments via the argc and argv parameters.
>
> Actually, Melzzzzz is right, although I can see why his description was
> confusing.
>
> On Unix, execv doesn't create the values for argc and argv; it just
> passes to the program the strings needed to populate argv. The C runtime
> needs to interpret (or "parse") the strings received from the kernel and
> create the values for argc and argv.
There are several steps between typing a command line at a shell prompt
and providing the arguments to the program via argc and argv. On
Unix-like systems, the only one of those steps that IMHO can reasonably
be called "parsing" is done by the shellf
[...]
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | m.labanowicz@gmail.com |
|---|---|
| Date | 2015-09-04 10:33 -0700 |
| Message-ID | <919a1e84-602a-4555-97a4-5b497d9c49b0@googlegroups.com> |
| In reply to | #69325 |
Ok, after adding a 'printf' in main function,
arguments which are passed to bar seems to have correct values.
But there is still invalid 'argv' in 'main' function.
Ok, this value is not important for this particular program,
but optimizer shouldn't change the program behavior
or perhaps optimizer in clang is so clever that it knows better what program should do :).
--{diff:beg}---------------------------------------------
@@ -21,6 +21,7 @@
}
int main(int argc, char * argv [])
{
+ printf("::::argv=%p\n", (void *)argv);
return bar(argc, argv);
}
#ifdef __cplusplus
--{diff:eof}---------------------------------------------
# clang --version && clang -Os main2.c -o a && ./a 1 2 3
clang version 3.5.2 (tags/RELEASE_352/final)
Target: x86_64-unknown-windows-cygnus
Thread model: posix
::::argv=0x0
argc=4, argv=0x24cb50
argv[0] = 0x18032a748 = "./a"
argv[1] = 0x18032a770 = "1"
argv[2] = 0x18032b7b8 = "2"
argv[3] = 0x18032b7e0 = "3"
# clang --version && clang main2.c -o a && ./a 1 2 3
clang version 3.5.2 (tags/RELEASE_352/final)
Target: x86_64-unknown-windows-cygnus
Thread model: posix
::::argv=0x24cb50
argc=4, argv=0x24cb50
argv[0] = 0x18032a748 = "./a"
argv[1] = 0x18032a770 = "1"
argv[2] = 0x18032b7b8 = "2"
argv[3] = 0x18032b7e0 = "3"
Regards
--
Maciek
[toc] | [prev] | [next] | [standalone]
| From | Noob <root@127.0.0.1> |
|---|---|
| Date | 2015-09-04 20:48 +0200 |
| Message-ID | <mscott$ten$1@dont-email.me> |
| In reply to | #69341 |
On 04/09/2015 19:33, m.labanowicz wrote: > Ok, after adding a 'printf' in main function, > arguments which are passed to bar seems to have correct values. > But there is still invalid 'argv' in 'main' function. If you're trying to get a bug fixed in clang/llvm, I think you need to go through the proper channels. Maybe you can reach out on IRC first: irc://irc.oftc.net/llvm Or report a bug: http://llvm.org/docs/HowToSubmitABug.html http://clang.llvm.org/get_involved.html https://llvm.org/bugs/ Regards.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c
csiph-web