Warning: may be used uninitialized in this function - c

Hitting below warning with new gcc version 6.X
Warning: 'temp' may be used uninitialized in this function [-Wmaybe-uninitialized]
Code:-
int temp;
if (logcat (MSPRO_P->regs[test],
byte, &temp, test) == FALSE){
memErrorMsgHistoryVa (MSPRO_MEMP, "Invalid Data Count 0 value");
MSPRO_P->flashCmdError = TRUE;
}

gcc isn't supposed to warn about passing a pointer to an uninitialized variable to a function it doesn't know anything about (the assumption is that the function will initialize it). So I'm pretty sure that gcc knows things about logcat and the uninitialized use is detected in there. Maybe it got inlined or such.
Example:
$ cat > foo.c
static int
bar(int *a)
{
return *a + *a;
}
int
foo(void)
{
int x;
int y = bar(&x);
return x + y;
}
$ cc -Wall -c foo.c
$
Here, despite it being blindingly obvious to humans, gcc doesn't actually know what happens inside the function bar. So no warning.
Let's help gcc to understand what's going on:
$ cc -O1 -Wall -c foo.c
foo.c: In function ‘foo’:
foo.c:4:12: warning: ‘x’ is used uninitialized in this function [-Wuninitialized]
return *a + *a;
~~~^~~~
foo.c:10:6: note: ‘x’ was declared here
int x;
^
$
Just turning on optimization helped gcc to see what's going on (probably some inlining happened).
From the minimal piece of code you've shown and the warning message, where it looks like you cut out the bit that actually tells you exactly where in your code the problem happens, I conclude that the problem is in your logcat function.

temp is uninitialized after int temp;.
logcat (MSPRO_P->regs[test], byte, &temp, test)
Since a pointer to temp is passed to the function, we, as programmers can guess that this function is supposed to initialize temp. But that is very difficult, if not impossible, for the compiler to assert with absolute certainity, specially when that function is in separate translation unit. From compilers perspective, there is no easy way to tell whether logcat will write to *temp or read it first in uninitialized state. And that's why the warning.
The easiest way to get rid of this warning is assign some initial value to temp, like:
int temp = 0

Related

How do I create arrays / average [duplicate]

Okay, so this is a stripped down variant of a bug I had. The bug was that I initialized an array using a variable that wasn't initialized. Earlier I used a function to declare the number of elements using a function, but after a cleanup I forgot about it and moved all declarations to the top of the function.
I used the flags -std=c99 -Wall -Wextra -pedantic -O, and usually gcc warns about values being used before they are uninitialized, but in this specific case it didn't. So, my question is:
Is this a bug in gcc or is it possible for f(&n) to post-initialize the array size in some weird way?
#include <stdio.h>
void f(int * x) {
*x = 8;
}
int main(void) {
int n;
float a[n]; // Compiler should warn that n may contain garbage
a[7] = 3.1415;
printf("%f\n", a[7]);
f(&n); // Removing this causes the compiler warn as expected
return 0;
}
EDIT: It may be this gcc bug?
GCC is accepting float a[n] as a variable-length array. It should, however, warn you that n contains garbage when it’s used. Perhaps VLA initialization is getting rearranged in a way that makes that fact non-obvious to the code generator? If n were initialized before use, moving the call to f() above the declaration of a would clearly be wrong, but this program produces undefined behavior.

Why doesn't gcc o warn when size of array is uninitialized in this code?

Okay, so this is a stripped down variant of a bug I had. The bug was that I initialized an array using a variable that wasn't initialized. Earlier I used a function to declare the number of elements using a function, but after a cleanup I forgot about it and moved all declarations to the top of the function.
I used the flags -std=c99 -Wall -Wextra -pedantic -O, and usually gcc warns about values being used before they are uninitialized, but in this specific case it didn't. So, my question is:
Is this a bug in gcc or is it possible for f(&n) to post-initialize the array size in some weird way?
#include <stdio.h>
void f(int * x) {
*x = 8;
}
int main(void) {
int n;
float a[n]; // Compiler should warn that n may contain garbage
a[7] = 3.1415;
printf("%f\n", a[7]);
f(&n); // Removing this causes the compiler warn as expected
return 0;
}
EDIT: It may be this gcc bug?
GCC is accepting float a[n] as a variable-length array. It should, however, warn you that n contains garbage when it’s used. Perhaps VLA initialization is getting rearranged in a way that makes that fact non-obvious to the code generator? If n were initialized before use, moving the call to f() above the declaration of a would clearly be wrong, but this program produces undefined behavior.

const pointer contract only hot air?

I am currently working on a project including a somewhat generic linked list implementation using void pointers. Providing some utitily functions for these lists, I decided to make the identifying functions of elements only take (const void *).
After adding the const keyword were necessary, I thought about how correct my code is now (if I implemented everything as it should be before).
As the compiler (GCC) didnt warn me, I decided to take a test.
I compiled the following code with "gcc -g -Wall test.c" and received no warnings whatsover by GCC.
#include <stdio.h>
#include <stdlib.h>
void testf(const void *testp){
*((int32_t *) testp) += 1;
}
void testf2(const int32_t *testp){
*((int32_t *) testp) += 1;
}
int main(){
int32_t testv = 0;
printf("%i \n", testv);
testf(&testv);
printf("%i \n", testv);
testf2(&testv);
printf("%i \n", testv);
return 0;
}
The output is the following:
0
1
2
I did not expect that C would actually crash by this, but I expected to receive a warning by the compiler. In this example im only casting, in my real functions I'm also assigning the const void pointers to a tmp variable.
Is this a bug?
Given how sophisticated todays compilers are, Id atleast expect a warning that Im casting a pointer to a non const pointer. If I change the cast and add the const keyword there too, GCC throws the usual error that I try to assign to a read only location
Am I supposed to rethink my trust to functions declaring const pointers? This is not what I understand as a contract :)
Is this a bug?
No, it's not. By casting you are saying "I know what I am doing" to the compiler.
But GCC does have an option -Wcast-qual which would catch if a qualifier is casted away intentionally.
I compiled the posted code using:
gcc -c -ggdb -Wall -Wextra -pedantic -std=c99 filename.c -o filename.o
(the following list is abbreviated for ease of reading)
error: 'int32_t' undeclared
error: expected expression before ')' token
*((int32_t *) testp) += 1;
warning: unused parameter 'testp'
void testf(const void *testp){
with lots more warnings and errors regarding int32_t
Surely your compiler stated these same items.
BTW: The missing header file is stdint.h.

Scoping rules for struct variables in GCC

Consider the following C program
#include <stdio.h>
typedef struct s {
int x;
} s_t;
int main() {
int x;
s_t a;
scanf("%d", &x);
if (x > 0) {
s_t a;
a.x = x;
}
printf("%d\n", a.x);
}
The a struct variable in the if branch clearly shadows the a struct variable in main. One would expect that the output in printf would be undefined, but with GCC the scoped variable seems to equal the main variable.
For example
gcc test.c -o test
echo 10 | ./test
will output 10.
On the other hand, running this through clang, does as expected
clang test.c -o test
echo 10 | ./test
outputs -2145248048.
Is this a GCC bug or is there some sort of undefined behaviour that this is triggering?
gcc 4.8.2
clang 3.4
As others mentioned, you're reading an uninitialized local variable and that's undefined. So, anything is legit. Having said that, there is a particular reason for this behavior: gcc reuses variables on the stack as much as it can (i.e., as long as the generated code is provably correct). You can fine-tune using the -fstack-reuse option.
To disable stack reuse:
gcc test.c -o test -fstack-reuse=none
echo 10 | ./test
4195808 # prints some random number.
To enable stack reuse for all variables:
gcc test.c -o test -fstack-reuse=all #, or -fstack-reuse=named_vars
echo 10 | ./test
10 # prints 10, as it reuses the space on the stack.
This is fully documented on GCC Code Generation Options.
One would expect that the output in printf would be undefined
It is undefined. Undefined behaviour means that anything can happen, including (but not limited to) any particular output.
In this case what's likely happening is that the compiler optimizes both a to have the same address.
No compiler bug, your program invokes undefined behavior.
You are reading an uninitialized automatic object and C says it has indeterminate value and that reading it is undefined behavior.
Give a.x (the one declared in main scope) a value to give your program a specified behavior.
Is this a GCC bug or is there some sort of undefined behavior that this is triggering?
It's undefined behavior. s_t a; in the if statement hides the previous declaration of a.
In the block
if (x > 0) {
s_t a;
a.x = x;
}
x is assigned to the local a.x. After this block, a is no longer available and in printf you are accessing an uninitialized variable. Uninitialized variables may invoke UB.

Unused Variable Error in C .. Simple Question

I get error in C(Error- Unused Variable) for variable when I type in following code
int i=10;
but when I do this(break it up into two statements)
int i;
i=10;
The error Goes away
..I am using Xcode(ver-4.1)(Macosx-Lion)..
Is something wrong with xcode....
No nothing is wrong the compiler just warns you that you declared a variable and you are not using it.
It is just a warning not an error.
While nothing is wrong, You must avoid declaring variables that you do not need because they just occupy memory and add to the overhead when they are not needed in the first place.
The compiler isn't wrong, but it is missing an opportunity to print a meaningful error.
Apparently it warns if you declare a variable but never "use" it -- and assigning a vale to it qualifies as using it. The two code snippets are equivalent; the first just happens to make it a bit easier for the compiler to detect the problem.
It could issue a warning for a variable whose value is never read. And I wouldn't be surprised if it did so at a higher optimization level. (The analysis necessary for optimization is also useful for discovering this kind of problem.)
It's simply not possible for a compiler to detect all possible problems of this kind; doing so would be equivalent to solving the Halting Problem. (I think.) Which is why language standards typically don't require warnings like this, and different compilers expend different levels of effort detecting such problems.
(Actually, a compiler probably could detect all unused variable problems, but at the expense of some false positives, i.e., issuing warnings for cases where there isn't really a problem.)
UPDATE, 11 years later:
Using gcc 11.3.0 with -Wall, I get warnings on both:
$ cat a.c
int main() {
int i = 10;
}
$ gcc -Wall -c a.c
a.c: In function ‘main’:
a.c:2:9: warning: unused variable ‘i’ [-Wunused-variable]
2 | int i = 10;
| ^
$ cat b.c
int main() {
int i;
i = 10;
}
$ gcc -Wall -c b.c
b.c: In function ‘main’:
b.c:2:9: warning: variable ‘i’ set but not used [-Wunused-but-set-variable]
2 | int i;
| ^
$
But clang 8.0.1 does not warn on the second program. (XCode probably uses clang.)
The language does not require a warning, but it would certainly make sense to issue one in this case. Tests on godbolt.org indicate that clang issues a warning for the second program starting with version 13.0.0.
(void) i;
You can cast the unused variable to void to suppress the error.

Resources