gcc compiler ignores uninitialized variable warning for debug build. This looks very weird for me, can some one help me to understand this ?
## Program
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int i, max;
int count;
if (argc < 2) {
return -1;
}
max = atoi(argv[1]);
for (i = 0; i < max; i++) {
count++;
}
printf("count is %d\n", count);
return 0;
}
gcc a.c -g -Wall -Werror
No warning
gcc a.c -O3 -Wall -Werror
a.c: In function ‘main’:
a.c:8:9: error: ‘count’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
int count;
^~~~~
cc1: all warnings being treated as errors
gcc version: 7.4.0
Though it may look weird, this behavior is documented for -Wmaybe-uninitialized gcc option:
-Wmaybe-uninitialized
For an automatic (i.e. local) variable, if there exists a path from the function entry to a use of the variable that is initialized, but there exist some other paths for which the variable is not initialized, the compiler emits a warning if it cannot prove the uninitialized paths are not executed at run time.
These warnings are only possible in optimizing compilation, because otherwise GCC does not keep track of the state of variables.
I guess the reason is that the cost of analyzing not initialized variables is too much for not optimizing compilation. That's why it is done only for optimizing one.
Related
I have to pass a string into a system call in xv6, so I know I have to use argstr(), my question lies with implementing it.
Here is what I have added to sysproc.c:
int sys_hello(char **str)
{
int n = 15;
argstr(n, **str);
for (int i = 0; i < n; i++){
cprintf("%c testplzprint",str[i]);
}
cprintf("Hello World\n");
return 0;
}
I am calling it from testcase.c:
#include "types.h"
#include "stat.h"
#include "user.h"
int main(void)
{
for (int i = 0; i < 5; i++){
hello("itworks");
}
exit();
}
I first implemented it without the testcase and argstr() and just printed hello and it worked well. I'm guessing my problem lies in how I am using argstr(). I really appreciate any help!
Update: sorry for not providing output, here it is right now.
js9313rr#smaug:/tmp/.x2go-js9313rr/media/disk/_cygdrive_C_Users_real0_Desktop_school_SPRING1_352/CSIS352/OS/OS lab 4/xv6-public-master$ make
gcc -fno-pic -static -fno-builtin -fno-strict-aliasing -O2 -Wall -MD -ggdb -m32 -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie -no-pie -c -o sysproc.o sysproc.c
sysproc.c: In function \u2018sys_hello\u2019:
sysproc.c:97:13: error: passing argument 2 of \u2018argstr\u2019 makes pointer from integer without a cast [-Werror=int-conversion]
argstr(n, **str);
^
In file included from sysproc.c:3:0:
defs.h:154:17: note: expected \u2018char **\u2019 but argument is of type \u2018char\u2019
int argstr(int, char**);
^~~~~~
cc1: all warnings being treated as errors
<builtin>: recipe for target 'sysproc.o' failed
make: *** [sysproc.o] Error 1
make the hello prototype clear:
Do you want a array of strings ou just a string?
Your sys_hello prototype is wrong, it should be sys_hello(void).
Here an example with an hello syscall taking one string as parameter:
int sys_hello(void)
char *string;
if(argstr(0, &string) < 0){
return -1;
}
cprintf(string);
return 0;
Why does this not work?:
prog.c file
#include <stdio.h>
int main(void)
{
int i, j;
printf("\n%d\n%d\n", i, j);
return 0;
}
debug file:
#!/bin/bash
g++ -Wall -Wextra -Wpedantic -O0 -g3 -fsanitize=address -o temp/debug.out src/prog.c
./temp/debug.out
running:
./debug
prog.c: In function ‘main’:
prog.c:6:9: warning: ‘i’ is used uninitialized in this function [-Wuninitialized]
printf("\n%d\n%d\n", i, j);
^~~~~~~~~~~~~~~~~~~~~~~~~~
prog.c:6:9: warning: ‘j’ is used uninitialized in this function [-Wuninitialized]
0
0
==90==LeakSanitizer has encountered a fatal error
==90==HINT: For debugging, try setting environment variable LSAN_OPTION=verbosity=1:log_threads=1
==90==LeakSanitizer does not work under ptrace (strace, gdb, etc)
I'm new to using debuging tools but there isn't much to read on this topic except man pages of compilers. So please can someone help me?
This was executed on Windows 10 subsystem for linux (Ubuntu) on freshly openned terminal.
I'd like to use -fno-sanitize=all option I found in man pages of gcc but it doesn't seem to say a word on any mistake I came up with.
I found out it was problem of WSL i used (I didn't think it was important to say i use one)
Turns out i need to write LSAN_OPTION=verbosity=1:log_threads=1; g++ -Wall...
Here is the content of source file get.c :
#include <stdio.h>
int main(){
//int i = 0;
char b[10];
gets(b);
puts(b);
return 0;
}
When I compile it with these command
gcc -o get get.c -Wall -Werror
The output is
/tmp/ccYEWZvx.o: In function `main':
get.c:(.text+0x10): warning: the `gets' function is dangerous and should not be used.
But when change the code to
#include <stdio.h>
int main(){
int i = 0; // **this line just be uncommented**
char b[10];
gets(b);
puts(b);
return 0;
}
Using the same command, the output is
cc1: warnings being treated as errors
get.c: In function 'main':
get.c:4: error: unused variable 'i'
So, why this unused variable warning be treated as error, while the use of gets() not?
The gets() warning is being issued by the linker not the compiler, so the compiler settings do not apply.
Only the linker is able to determine that the symbol is resolved with the standard library gets() rather than some other implementation with the same name.
To instruct the linker to treat warnings as errors you need to pass it the --fatal-warnings option. In turn when not invoking the linker directly, options are passed to the linker by gcc using the -Wl option in a comma separated list:
gcc -o get get.c -Wall -Werror -Wl,--fatal-warnings
Note that the GNU linker is documented separately from the compiler, as part of binutils. The linker options are described here.
If you look at the output from the first example, it says the "error" is in an object file, which means it is generated by the linker.
The second error is generated by the compiler, which means there is no object file being generated and so the linker will not be invoked.
-Werror make all warnings as errors, to print only security warnings you can use: -Wformat -Wformat-security
You can read warnings options here https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
The compiler abort the compilation if an error is occurred, instead it continue the compilation if there are one or more warnings.
I have the following code, saved on Coding Ground here:
#include <stdio.h>
void foo(int const *x)
{
printf("Hello, %d!\n", *x);
}
int main()
{
int y;
foo(&y);
y = 3;
printf("Hello, World %d!\n", y);
return 0;
}
I compile with:
gcc -std=c99 -Wall -Wextra -Wuninitialized -o main *.c
However, I get no warning about taking a const pointer of an uninitialised variable, and I cannot find a suitable flag.
Note: pasting the code into Gimpel's Online Lint gives me the expected:
test.c 12 Warning 603: Symbol 'y' (line 10) not initialized
-Wuninitialized
Warn whenever an automatic variable is used without first being initialized.
These warnings are possible only in optimizing compilation, because they require data-flow information that is computed only when optimizing. If you don't specify `-O', you simply won't get these warnings.
If you try to compile with:
gcc -std=c99 -Wall -Wextra -Wuninitialized -O2 -o main *.c
The warning will be:
pippo.c: In function ‘main’:
pippo.c:56:5: warning: ‘y’ is used uninitialized in this function [-Wuninitialized]
printf("Hello, %d!\n", *x);
^
pippo.c:61:9: note: ‘y’ was declared here
int y;
^
Why should be something wrong in here ? you just passed that variable through that function which take as arg a Pointer. You did not passed its value, you passed its address with & so the compiler doesn't see this as a wrong, even if you later try to print its garbage value. Remember that you print at this point the value of the Pointer (*x) and not the variable itself.
Aren't variables initialized with a garbage value if you do not do it your self ?
But if you do not use a pointer:
#include <stdio.h>
void foo(int const x)
{
printf("Hello, %d!\n", x);
}
int main(void){
int y;
foo(y);
y = 3;
printf("Hello, World %d!\n", y);
return 0;
}
Things ar different now and compiler know about this:
program.c:12:5: error: ‘y’ is used uninitialized in this function [-Werror=uninitialized]
foo(y);
^
cc1: all warnings being treated as errors
I was reading C programming from a book that says all variables have to be declared in the beginning of the function. I tried following code but didn't issue any error. I am using mingw and codeblocks. The code is as follows:
#include <stdio.h>
int main()
{
int i=10;
printf("%d\n",i);
int j=20;
printf("%d\n",j);
return 0;
}
Do I have to change any compiler setting or something to make it compatible with the standard given in the book?
I am using -std=c89 compiler option. See the compilation messages below:
-------------- Clean: Debug in HelloWorld (compiler: GNU GCC Compiler)---------------
Cleaned "HelloWorld - Debug"
-------------- Build: Debug in HelloWorld (compiler: GNU GCC Compiler)---------------
mingw32-gcc.exe -Wall -std=c89 -g -c D:\MyCodeBlocksProjects\HelloWorld\main.c -o obj\Debug\main.o
mingw32-g++.exe -o bin\Debug\HelloWorld.exe obj\Debug\main.o
Output size is 68.53 KB
Process terminated with status 0 (0 minutes, 0 seconds)
0 errors, 0 warnings (0 minutes, 0 seconds)
all variables have to be declared in the beginning of the function.
To be precise, they have to be declared in the beginning of a block. And this is only true in C89. C99 has removed this limit. So you can change your compiler to strict C89 mode. For example, for GCC, it's -std=c89 option. To obtain all the diagnostics required by the standard, you should also specify the option -pedantic.
To demonstrate what I mean by in the beginning of a block, this is legal C89 syntax:
void foo()
{
int x = 1;
x = x + 1;
{
int y = 42; /**OK: declaration in the beginning of a block*/
}
}