What could be case of use `int x = x;` expression (C language)? - c

I have a lib written in C. In code i found a few lines like this int x = x;. I need to rewrite all this pieces of code for compilation with /Zw flag. In some places that mean's int x = some_struct->x;, but in another cases i don't understand what is it. In some places it first use of x variable. So in which cases could be used such int x = x; expression.
void oc_enc_tokenize_dc_frag_list(oc_enc_ctx *_enc,int _pli,
const ptrdiff_t *_coded_fragis,ptrdiff_t _ncoded_fragis,
int _prev_ndct_tokens1,int _prev_eob_run1){
const ogg_int16_t *frag_dc;
ptrdiff_t fragii;
unsigned char *dct_tokens0;
unsigned char *dct_tokens1;
ogg_uint16_t *extra_bits0;
ogg_uint16_t *extra_bits1;
ptrdiff_t ti0;
ptrdiff_t ti1r;
ptrdiff_t ti1w;
int eob_run0;
int eob_run1;
int neobs1;
int token;
int eb;
int token1=token1;
int eb1=eb1;
/*Return immediately if there are no coded fragments; otherwise we'd flush
any trailing EOB run into the AC 1 list and never read it back out.*/
if(_ncoded_fragis<=0)return;
frag_dc=_enc->frag_dc;
dct_tokens0=_enc->dct_tokens[_pli][0];
dct_tokens1=_enc->dct_tokens[_pli][1];
extra_bits0=_enc->extra_bits[_pli][0];
extra_bits1=_enc->extra_bits[_pli][1];
ti0=_enc->ndct_tokens[_pli][0];
ti1w=ti1r=_prev_ndct_tokens1;
eob_run0=_enc->eob_run[_pli][0];
/*Flush any trailing EOB run for the 1st AC coefficient.
This is needed to allow us to track tokens to the end of the list.*/
eob_run1=_enc->eob_run[_pli][1];
if(eob_run1>0)oc_enc_eob_log(_enc,_pli,1,eob_run1);
/*If there was an active EOB run at the start of the 1st AC stack, read it
in and decode it.*/
if(_prev_eob_run1>0){
token1=dct_tokens1[ti1r];
eb1=extra_bits1[ti1r];
ti1r++;
eob_run1=oc_decode_eob_token(token1,eb1);
code exaple - variable token1 - it's first use of token1 in file and token1 never meets in other files, it's not global, not static anywhere...
Update with /Zw flag:error C4700: uninitialized local variable 'token1' used
without flag: all works fine with this lib
Update 2
it's theora 1.1.1 lib
Resume
on advice of the guys in comments, i replace every int x = x; with int x = 0 and everything works fine =) everyone thanx for answers

If you literally have int x = x;, there isn't much use of it. This piece attempts to initialize x with itself, that is, with the value of an uninitialized variable.
This may suppress some compiler warnings/errors related to uninitialized or unused variables. But some compilers can catch these dubious cases as well.
This probably also results in undefined behavior from the C standard's view point.
EDIT: Random Number Bug in Debian Linux is an article (with further links) about use and abuse of uninitialized variables and the price one may pay one day.

It prevents the compiler from emitting a warning that the variable is unused.

Related

frama-c slicing plugin appears to discard used stack values

Problem description
I'm developing a frama-c plugin that uses the slicing plugin as a library to remove unused bits of automatically generated code. Unfortunately the slicing plugin drops a bunch of stack values, which are actually used. They are used in so far as their addresses are contained in structures that are handed of to abstract external functions.
Simple example
This is a simpler example that models the same general structure I have.
/* Abstract external function */
void some_function(int* ints[]);
int main() {
int i;
int *p = &i;
int *a[] = { &p };
some_function(a);
return 0;
}
When slicing this example with frama-c-gui -slice-calls some_function experiment_slicing.c (I haven't figures out how to see the slicing output when invoking the command line without gui) it drops everything but the declaration int *a[]; and the call to some_function.
Attempted fixes
I tried fixing it by adding ACSL annotations.
However what I believed to be the sensible specification (see below) did not work
/*# requires \valid(ints) && \valid(ints[0]);
*/
void some_function(int* ints[]);
I then tried with an assign (see below) which does have the desired behaviour. however it is not a correct specification, since the function never actually writes to the pointer but needs to read it for correct functionality. I am worried that if I move ahead with such an incorrect specification it will lead to weird problems down the line.
/*# requires \valid(ints) && \valid(ints[0]);
assigns *ints;
*/
void some_function(int* ints[]);
You are on the right track: it is the assigns clause that you should use here: it will indicate which parts of the memory state are concerned by a call to an undefined function. However, you need to provide a complete assigns clause, with its \from part (that indicates which memory location are read to compute the new value of the memory location written to).
I have added an int variable to your example, as your function isn't returning a result (void return type). For a function that is returning something, you should also have a clause assigns \result \from ...;:
int x;
/*# assigns x \from indirect:ints[..], *(ints[..]); */
void some_function(int* ints[]);
int main() {
int i;
int*p = &i;
int *a[] = { &p };
some_function(a);
return 0;
}
The assigns clause indicates that some_function might change the value of x, and that the new value will be computed from the addresses stored in ints[..]
(the indirect label tells that we're not using their value directly, this is described in more detail in section 8.2 of Eva's manual), and their content.
using frama-c -slice-calls some_function file.c -then-last -print (the last arguments are here to print the resulting file on the standard output: -then-last indicates that the following options should operate on the last Frama-C project created, in that case the one resulting from the slicing, and -print prints the C code of said project. You may also use -ocode output.c to redirect the pretty-printing of the code into output.c.) gives the following result:
* Generated by Frama-C */
void some_function(int **ints);
void main(void)
{
int i;
int *p = & i;
int *a[1] = {(int *)(& p)};
some_function(a);
return;
}
Note in addition that your example is not well-typed: &p is a pointer to pointer to int, and should thus be stored in an int** array, not an int* array. But I assume that it only stems from reducing your original example and is does not matter much for slicing itself.

Pointers in C and casting

I've started learning pointers this time. Im trying to read bytes from this array. Task is almost done but CLang keep warns me with warning I don't understand. Here's my code.
Warning says : " Function call argument is an uninitialized value"
int main(void)
{
int tab[] = {67305985,134678021,202050057};
int *pp=0;
pp=tab;
char *wsk=(char*)pp;
for (int i = 0; i < 12; i++)
{
if((wsk+i)!=(void*)NULL)
printf("%d ",*(wsk+i)); // warning on this line
else
return 0;
}
}
These warnings are from Clang Static Analyzer (or whatever they call it these days).
It looks like a false positive to me, if we assume that int is at least 4 bytes and the real code has #include <stdio.h> and no other changes.
If you're using the latest version of the analyzer, you could file a clang bug report. Well -- you could if they allowed people who don't already have accounts to file bug reports. Maybe someone else reading this thread can do it.
Note: it would help the question to post exactly which version of the analyzer you are running (this may be different to the compiler you're using to build -- some IDEs use different compilers for building than for these inline messages).
This if statement
if((wsk+i)!=(void*)NULL)
does not make sense. The macro NULL is already a null pointer constant. So there is no sense to cast it to void *.
And the pointer wsk+i can not be equal to NULL in this loop because initially it points to an object.
Just remove the if statement and output each character in the loop.
And it is a bad idea to use magic numbers like 12 used in the loop.
You could write for example
const size_t N = sizeof( tab ) / sizeof( *tab );
and then in the loop
for ( size_t i = 0; i < N * sizeof( int ); i++ )
//...
As for the warning then it is irrelative to the presented code provided that you included the header <stdio.h>.
wsk will never be null, since you've set it to be the same as tab (arrays, in C/C++ are just pointers to a block of data. The warning is telling you that no matter how much you add to wsk it will always be non-null. What you need to do is limit your iterations in the loop to the number of valid items in the array, since C/C++ arrays have no terminators of any kind.
The printf might just be confusing CLang. Try printf("%d ", wsk[i]);

C gives different output based on optimization level (new example)

Based on this very good blog post, The Strict Aliasing Situation is Pretty Bad, I've placed the piece of code online for you to test it:
http://cpp.sh/9kht (output changes between -O0 and -O2)
#include <stdio.h>
long foo(int *x, long *y) {
*x = 0;
*y = 1;
return *x;
}
int main(void) {
long l;
printf("%ld\n", foo((int *)&l, &l));
}
Is there some sort of undefined behaviour here?
What is going on internally when we choose the -O2 level?
Yes, this program has undefined behavior, because of the type-based aliasing rules, which can be summarized as "you cannot access a memory location declared with type A through a pointer of type B, except when B is a pointer to a character type (e.g. unsigned char *)." This is an approximation, but it is close enough for most purposes. Note that when A is a pointer to a character type, B may not be something else—yes, this means the common idiom of accessing a byte buffer "four at a time" through an uint32_t* is undefined behavior (the blog post also touches on this).
The compiler assumes, when compiling foo, that x and y may not point to the same object. From this, it infers that the write through *y cannot change the value of *x, and it can just return the known value of *x, 0, without re-reading it from memory. It only does this when optimization is turned on because keeping track of what each pointer can and cannot point to is expensive (so the compilation is slower).
Note that this is a "demons fly out of your nose" situation: the compiler is entitled to make the generated code for foo start with
cmp rx, ry
beq __crash_the_program
...
(and a tool like UBSan might do just that)
Said another way, the code (int *)&l says treat the pointer as a pointer to an int. It does not convert anything. So, the (int *) tells the compiler to allow you to pass a long* to a function expecting an int*. You are lying to it. Inside, foo expects x to be a pointer to an int, but it isn't. The memory layout is not what it should be. Results are, as you see, unpredictable.
On another note, I wouldn't ever use l (ell) as a variable name. It is too easily confused with 1 (one). For example, what is this?
int x = l;

Pointer pointing to itself C

I'm writing a function called at the end of a recursive chain. This function needs to figure out where it is in memory at the instance of when it's being called. The code is as follows:
void recover ()
{
int * x = (int *)&x;
}
The problem is the program just skips over this statement as if it was never written. I've verified this in GDP. Can you think of any reason why this line is being ignored?
Thanks!
Declare the variable as volatile. It should prevent compiler optimizations.
volatile int * x = (int *)&x;
If you are compiling with optimization turned on, then this code is probably optimized out due to no effect on the program. Use -O0 option.
The code you wrote is probably undefined behavior since you're casting a pointer to a pointer to an int to a pointer to an int.
A pointer can't conceptually point to itself since you would never be able to achieve the right level of indirection. Here's why:
Declaration | Type | Type after using the & operator
--------------------------------------------------------------
int x; | int | &x is an (int*)
int* x; | int * | &x is an (int**)
int** x; | int ** | &x is an (int***)
However, a void* is the only type of pointer I can think of that might be allowed to break this rule, but I'm not sure if it would be legal according to the standard.
I would propose you write the following instead of what you have:
int* recover ()
{
int local = 0;
return &local;
}
And compile it with no optimizations like #ysap suggests.
Still from your example it seems like you're trying to figure out where the top of the stack is and that is very easily done in assembly. All you need to do is read the stack pointer. However, this isn't so cleanly exposed in C. Though GCC does have some helper functions for similar tasks I haven't found one for the stack pointer.
I would personally resort to inline assembly since whatever is written will probably not be portable anyway.
Additionally, if I'm understanding your question right it is most likely a duplicate of this question so it would pay to read those answers as well.
Edit: It should be equivalent to return the address of the frame of the current function which can be done by using a GCC builtin function __builtin_frame_address (unsigned int level) linked earlier. The code would look like this:
int* recover()
{
return (int*)__builtin_frame_address(0);
}

What should happen, when we try to modify a string constant?

#include<stdio.h>
#include<string.h>
int main()
{
int i, n;
char *x="Alice"; // ....... 1
n = strlen(x); // ....... 2
*x = x[n]; // ....... 3
for(i=0; i<=n; i++)
{
printf("%s ", x);
x++;
}
printf("\n");
return 0;
}
String constant cannot be modified. In the above code *x means 'A'. In line 3 we are trying to modify a string constant. Is it correct to write that statement? When I run this code on Linux, I got segmentation fault. But on www.indiabix.com, they have given answer:
If you compile and execute this program in windows platform with Turbo C, it will give lice ice ce e It may give different output in other platforms (depends upon compiler and machine). The online C compiler given in this site will give Alice lice ice ce e as output (it runs on Linux platform).
Your analysis is correct. The line
*x = x[n];
is trying to modify a string literal, so it's undefined behavior.
BTW, I checked the website that you linked. Just browsing it for two minutes, I've already found multiple incorrect code samples (to name a few, using gets, using char(not int) to assign return value of getchar, etc), so my suggestion is don't use it.
Your analysis is correct, but doesn't contradict what you quoted.
The code is broken. The answer already acknowledges that it may behave differently on different implementations, and has given two different outputs by two different implementations. You happen to have found an implementation that behaves in a third way. That's perfectly fine.
Modification of a string literal is Undefined Behaviour. So the behaviour you observe, and the two described, are consistent with the requirements of the C standard (as is emailing your boss and your spouse, or making demons fly out of your nose). Those three are all actually quite reasonable actions (modify the 'constant', ignore the write, or signal an error).
With GCC, you can ask to be warned when you assign the address of a string literal to a pointer to (writable) char:
cc -g -Wall -Wextra -Wwrite-strings -c -o 27211884.o 27211884.c
27211884.c: In function ‘main’:
27211884.c:7:13: warning: initialization discards ‘const’ qualifier from pointer target type [enabled by default]
char *x="Alice"; // ....... 1
^
This warning is on by default when compiling C++, but not for C, because char* is often used for string literals in old codebases. I recommend using it when writing new code.
There are two correct ways to write the code of the example, depending on whether you want your string to actually be constant or not:
const char *x = "Alice";
char x[] = "Alice";
In this code, the memory for "Alice" will be in the read-only data section of the executable file and x is a pointer pointing to that read-only location. When we try to modify the read-only data section, it should not allow this. But char *x="Alice"; is telling the compiler that x is declared as a pointer to a character, i.e. x is pointing to a character which can be modified (i.e. is not read-only). So the compiler will think that it can be modified. Thus the line *x = x[n]; will behave differently on different compilers. So it will be undefined behavior.
The correct way of declaring a pointer to a assign string literal is as below:
const char *x ="Alice";
Only then can the behavior of the compiler be predicted.

Resources