I have defined a variable with an initial value.
When stepping through the code:
I can see the initial value
My function changes the value
When I use the variable later it has the wrong value
What is happening?
Note: this is intended as a reference question for common problems. If the generic answers here don't help you, post a question containing your complete, actual code.
There are several reasons why a variable might not keep a value. While some are arcane and difficult to debug, some of the most common reasons include:
The variable is modified by an interrupt
//---in main()---
unint8_t rxByte = 0;
printf("%d", rxByte); //prints "0"
//---later in Uart0_Rx_Handler()---
rxByte = U0RXREG; //rxByte set to (for example) 55
//---later in main()---
printf("%d", rxByte); //still prints "0"!!!
If a variable is modified by an interrupt handler, it needs to be declared volatile. Volatile lets the compiler know that the variable could be modified asynchronously and that it shouldn't used a cached copy in a register.
//---in main()---
volatile unint8_t rxByte = 0;
printf("%d", rxByte); //prints "0"
//---later in Uart0_Rx_Handler()---
rxByte = U0RXREG; //rxByte set to 55
//---later in main()---
printf("%d", rxByte); //corectly prints 55
Overrunning an array's bounds
There are no checks in C to prevent you from going beyond the bounds of an array.
int array[10];
int my_var = 55;
printf("%d", my_var); //prints "55"
for(i=0; i<11; i++) // eleven is one too many indexes for this array
{
array[i] = i;
}
printf("%d", my_var); // prints "11"!!!
In this case, we go through the loop 11 times, which is one index bigger than the array. In most compilers, this will result in overwriting variables declared after the array (anywhere on the page, they don't even have to be declared on the next line). This scenario can occur in many different circumstances, including multi-dimensional arrays and stack corruption.
Forgetting to dereference a pointer
While trivial, forgetting the asterisk on a pointer when making assignments will not set the variable correctly
int* pCount;
pCount = 10; //forgot the asterisk!!!
printf("%d", *pCount); //prints ??
Masking a variable with the same name
Reusing a variable name in an inner scope (like inside an if/for/while block or inside a function) hides a variable with the same name elsewhere.
int count = 10; //count is 10
if(byteRecevied)
{
int count = U0RXREG; //count redeclared!!!
DoSomething(count);
printf("%d", count); //prints "55"
}
printf("%d", count); //prints "10"
I'd like to add another possible reason to Zack's excellent answer.
Optimisation
This one frequently surprises me. A good optimising compiler will notice when two different variables are never used at the same time, and will optimise the program by giving those variables the same address in memory. When you are stepping through the code, you may see a variable apparently changing in the watch window. But what's really happening is that the variable that shares its address is being written to.
The other trick the compiler pulls is simply getting rid of a variable that it realises isn't necessary. Sometimes you might be doing the equivalent of this in your code:
force_a = mass_a * acceleration_a
force_b = mass_b * acceleration_b
total_force = force_a + force_b
The compiler sees that there's no real need for the variables force_a and force_b, and so changes the code to this:
total_force = (mass_a * acceleration_a) + (mass_b * acceleration_b)
You'll never see force_a and force_b being updates, but you'll still be able to add them to the watch window.
When I step through my program, I'm convinced that some variable or other has the wrong value in it, but when I let my program run through without stepping, it seems to work. Check that this isn't happening to you.
Added:
As Ashish Kulkarni mentioned, you can check this by turning off optimisation.
Related
I am a beginner is Computer Science and I recently started learning the language C.
I was studying the for loop and in the book it was written that even if we replace the initialization;testing;incrementation statement of a for loop by any valid statement the compiler will not show any syntax error.
So now I run the following program:
#include<stdio.h>
int main()
{
int i;
int j;
for(i<4;j=5;j=0)
printf("%d",i);
return 0;
}
I have got the following output.
OUTPUT:
1616161616161616161616161616161616161616.........indefinitely
I understood why this is an indefinite loop but i am unable to understand why my PC is printing this specific output? Is there any way to understand in these above kind of programs what the system will provide us as output?
This is a case of undefined behaviour.
You have declared i so it has a memory address but haven't set the value so its value is just whatever was already in that memory address (in this case 16)
I'd guess if you ran the code multiple times (maybe with restarts between) the outputs would change.
Some more information on uninitialized variables and undefined behaviour: https://www.learncpp.com/cpp-tutorial/uninitialized-variables-and-undefined-behavior/
Looks like i was never initialized, and happens to contain 16, which the for loop is printing continuously. Note that printf does not add a new line automatically. Probably want to read the manual on how to use for.
To better understand what is going on, you can add additional debugging output to see what other variables are set to (don't forget the \n newline!) but really problem is the for loop doesn't seem right. Unless there's something going on with j that you aren't showing us, it really doesn't belong there at all.
You are defining the variable i but never initializing it, instead, you are defining the value for j but never using it.
On a for loop, first you initialize the control variable, if you haven't already done it. Then you specify the condition you use to know if you should run another iteration or not. And last but not least, change the value of the control variable so you won't have infinite loops.
An example:
#include <stdio.h>
int main()
{
// 1. we declare i as an integer starting from 1
// 2. we will keep iterating as long as i is smaller than 10
// 3. at the end of each iteration, we increment it's value by 1
for (int i = 1; i < 10; i++) {
printf("%d\n", i);
}
return 0;
}
so I'm slowly trying to learn C from scratch.
I'm at a point in the book I'm using where an exercise is proposed: use nested loops to find Pythagorean triplets. Now I'll show the code.
#include <stdio.h>
int main(void){
int lato1=1;
int lato2=1;
int ipotenusa=1;
for(;lato1 <= 500; lato1++){
for(;lato2 <= 500; lato2++){
for(;ipotenusa <= 500; ipotenusa++){
if (((lato1 * lato1)+(lato2 * lato2))==(ipotenusa*ipotenusa)){
printf("Tripletta %10d %10d %10d\n",lato1,lato2,ipotenusa);
}
}
}
}
return 0;
}
now, apart from terrible formatting and style, apart from the shi*t optimization,
the code as shown, doesnt work.
It only execute the inner most loop, and then the program ends.
If, however, I initialize each variable/counter inside each loop then it works.
Why?
I read that for loop initialization is valid even whitout no arguments (;;) but in this case I just wanted to initialize those variables before the loop, let's say because I wanted to access those value after the loop is done, it just doesn't seem to work like it's supposed to.
English is not my primary language so apologies in advance for any mystake.
Can somebody explain what is the problem?
Edit 1: So, I don't know if it was my bad English or something else.
I said, if I declare and initialize the variables before the loop, like in the code I've shown you, it only goes through the inner most loop (ipotenusa) and it does so with the following output values: 1 1 1 then 1 1 2 then 1 1 3 and so on, where the only increasing number is the last one (ipotenusa); AFTER we reach 1 1 500 the programs abruptily ends.
I then said that if I initialize the variables as normal, meaning inside the for loop instruction, then it works as intended.
Even if declared earlier there is NO reason it should't work. The variable's value it's supposed to increase. Up until now the only useful answer was to initialize a variable outside the loop but assign a value to it in the loop statement, but this is not at the end the answer I need, because I should be able to skip the initialization inside the loop statement altogether.
EDIT 2: I was wrong and You guys were right, language barrier (most likely foolishness, rather) was certainly the cause of the misunderstanding lol. Sorry and Thanks for the help!
You accidentally answered your own question:
...in this case I just wanted to initialize those variables before the loop, let's say because I wanted to access those value after the loop is done...
Think about the value of ipotenusa...or have your program print out the value of each variable at the start of each loop for debugging purposes. It'll look something like the following log.
lato1: 1
lato2: 1
ipotenusa: 1
ipotenusa: 2
ipotenusa: 3
ipotenusa: 4
ipotenusa: 5
lato2: 2
lato2: 3
lato2: 4
lato2: 5
lato1: 2
lato1: 3
lato1: 4
lato1: 5
The inner loops never "reset," because you're saving the value. You're not wrong on either count, but you've set up two requirements that conflict with each other, and the C runtime can only give you one.
Basically, lato2 and ipotenusa need to be initialized (but not necessarily declared) in their for statements, so that they're set up to run again.
int lato1=1;
int lato2;
int ipotenusa;
for(;lato1 <= 5; lato1++){
for(lato2 = 1;lato2 <= 5; lato2++){
for(ipotenusa = 1;ipotenusa <= 5; ipotenusa++){
if (((lato1 * lato1)+(lato2 * lato2))==(ipotenusa*ipotenusa)){
printf("Tripletta %10d %10d %10d\n",lato1,lato2,ipotenusa);
}
}
}
}
It's worth pointing out that, even though the specification might (or might not; I don't remember and am too fuzzy to look it up, right now) say that the loop variables only exist during the loop, I've never seen an implementation actually do that, so you'll see a lot of code out there that defines the variable inside of for and uses it after. It's probably not great and a static checker like lint might complain, but it's common enough that it'll pass most code reviewers, to give you a sense of whether it can be done.
Your code does exactly what you told it to do.
If you initialise lato2 with a value of 1, what makes you think that the initialisation will be repeated at the start of the inner for loop? Of course it isn't. You told the compiler that you didn't want it to be initialised again. After that loop executed the first time, lato2 has a value of 501, and it will keep that value forever.
Even if it hadn't produced a bug, putting the initialisation and the for loop so far apart is very, very bad style (wouldn't pass a code review in a professional setting and therefore would have to be changed).
for (int lato2 = 1; lato2 <= 500; ++lato2) is clear, obvious, and works.
One approach would be - declaring variables outside of the loop and initialize them inside. This way, you can access the variables after the loops.
#include <stdio.h>
int main(void){
int lato1, lato2, ipotenusa;
for(lato1=1; lato1 <= 500; lato1++){
for(lato2=1; lato2 <= 500; lato2++){
for(ipotenusa=1; ipotenusa <= 500; ipotenusa++){
if (((lato1 * lato1)+(lato2 * lato2))==(ipotenusa*ipotenusa)){
printf("Tripletta %10d %10d %10d\n",lato1,lato2,ipotenusa);
}
}
}
}
return 0;
}
You are using variables that are initialized outside of the for loops. Usually what happens is when we use inner loops(nested loops) we intended to initialize it with base value everytime but in your case it is never going to do that. Since you have initialized variable out side of the for loops so it will persist its value through out its life time of course which is main function in this case.
ive got a C program that gets caught in a for loop that it shouldn't, running it with
valgrind --tool=memcheck --leak-check=yes a.out
doesnt return anything even up until the program gets caught. is there a way to change the settings of valgrind to help me find the leak? as many have pointed out, it wouldnt be considered a leak, apologies
thanks in advance
here is the loop in question
int clockstate=0;
int clocklength=0;
int datalength=0;
int datastate=0;
int dataloc = 9;
((((some other code that i don't think is important to this part))))
int dataerr[13] = {0};
int clockerr[13] = {0}; // assumes that spill does not change within an event.
int spill=0;
int k = 0;
spill = Getspill(d+4*255+1); // get spill bit from around the middle
//printf("got spill: %d \n", spill); // third breakpoint
for( k = 0; k < 512; k++)
{
// Discardheader(d); // doesnt actually do anything, since it's a header.f
int databit = Getexpecteddata(d+4*k+1);
printf("%d ",k);
int transmitted = Datasample(&datastate, &datalength, d+4*k+2,dataerr,dataloc, databit);
printf("%d ",k);
Clocksample(&clockstate, &clocklength, d+4*k+3,clockerr, transmitted);
printf("%d \n",k);
// assuming only one error per event (implying the possibility of multi-error "errors"
// we construct the final error at the very end of the (outside this loop)
}
and the loop repeats after printing
254 254 254
255 255 255
256 256 1 <- this is the problem
2 2 2
3 3 3
edit** so i've tracked down where it is happening, and at one point in
void Clocksample (int* state, int* length, char *d, int *type, int transbit);
i have code that says *length = 1; so it seems that this command is somehow writing onto int k. my question now is, how did this happen, why isnt it changing length back to one like i want, and how do i fix it. if you want, i can post the whole code to Clocksample
Similar to last time, something in one of those functions, Clocksample() this time, is writing to memory that doesn't belong to the data/arrays that the function should be using. Most likely an out of bounds array write. Note: this is not a memory leak, which is allocating then losing track of memory blocks that should be freed.
Set a breakpoint at the call to Clocksample() for when k is 256. Then step into Clocksample(), keeping a watch on k (or the memory used by k). You can probably also just set a hardware memory write breakpoint on the memory allocated to k. How you do any of this depends on the debugger you're using.
Now single-step (or just run to the return of Clocksample() if you have a hardware breakpoint set) and when k changes, you'll have the culprit.
Please note that Valgrind is exceedingly weak when it comes to detecting stack buffer overflows (which is what appears to be happening here).
Google address-sanitizer is much better at detecting stack overflows, and I suggest you try it instead.
So your debugging output indicates that k is being changed during the call to your function Clocksample. I see that you are passing the addresses of at least two variables, &clockstate and &clocklength into that call. It seems quite likely to me that you have an array overrun or some other wild pointer in Clocksample that ends up overwriting the memory location where k is stored.
It might be possible to narrow down the bug if you post the code where k is declared (and whatever other variables are declared nearby in the same scope). For example if clocklength is declared right before k then you probably have a bug in using the pointer value &clocklength that leads to writing past the end of clocklength and corrupting k. But it's hard to know for sure without having the actual layout of variables you're using.
valgrind doesn't catch this because if, say, clocklength and k are right next to each other on the stack, valgrind can't tell if you have a perfectly valid access to k or a buggy access past the end of clocklength, since all it checks is what memory you actually access.
A sample problem asks us to consider the code below and predict what will be printed out by the function funct_1:
void func_1(int i, int j) {
printf("i is %d, j is %d\n", i, j);
}
/* ... */
/* somewhere in the code, a call to func_1 */
int i = 30;
func_1(i, i++);
/* ... */
I thought that when parameters are passed in this form where they are incremented, it is impossible to predict when the compiler would increment i. The solution, however, is:
The values in the argument are passed as an attack to the function, hence 'j' receives
a value '30' and then i receives the incremented value which is '31'.
Output: i is 31, j is 30
Could someone please explain what an attack to a function is and how this happens?
It is not impossible to predict; compilers work in a deterministic manner, even in the grey areas poorly covered or not covered by the specs. With this specific compiler arguments are pushed right to left, and the post-increment occurs shortly after the right parameter has been pushed.
The solution is wrong in general. You are correct; the behaviour of the code is undefined. On some compilers, the answer might be 30 and 31; on others, it might be 30 and 30; on others, it might be 31 and 31; and others might simply erase all the files on your hard drive (because undefined behaviour is undefined). Fortunately, the radical, remove-all-traces-of-the-trouble behaviour is relatively unlikely in a compiler.
For some specific compiler on some specific platform, the solution is probably correct.
Actually, I think that it is not possible to get 31 for j in func_1() - but an operation sequence that produces 30 and 30 is easily imaginable: the value of i is pushed twice, then I is incremented, then the function is called.
I found some code and I am baffled as to how the loop exits, and how it works. Does the program produce a deterministic output?
The reason I am baffled is:
1. `someArray` is of size 2, but clearly, the loop goes till size 3,
2. The value is deterministic and it always exits `someNumber` reaches 4
Can someone please explain how this is happening?
The code was not printing correctly when I put angle brackets <> around include's library names.
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
int main() {
int someNumber = 97;
int someArray[2] = {0,1};
int findTheValue;
for (findTheValue=0; (someNumber -= someArray[findTheValue]) >0; findTheValue++) {
}
printf("The crazy value is %d", findTheValue);
return EXIT_SUCCESS;
}
Accessing an array element beyond its bounds is undefined behavior. That is, the program is allowed to do anything it pleases, reply 42, eat your hard disk or spend all your money. Said in other words what is happening in such cases is entirely platform dependent. It may look "deterministic" but this is just because you are lucky, and also probably because you are only reading from that place and not writing to it.
This kind of code is just bad. Don't do that.
Depending on your compiler, someArray[2] is a pointer to findTheValue!
Because these variables are declared one-after-another, it's entirely possible that they would be positioned consecutively in memory (I believe on the stack). C doesn't really do any memory management or errorchecking, so someArray[2] just means the memory at someArray[0] + 2 * sizeof(int).
So when findTheValue is 0, we subtract, then when findTheValue is 1, we subtract 1. When findTheValue is 2, we subtract someNumber (which is now 94) and exit.
This behavior is by no means guaranteed. Don't rely on it!
EDIT: It is probably more likely that someArray[2] just points to garbage (unspecified) values in your RAM. These values are likely more than 93 and will cause the loop to exit.
EDIT2: Or maybe someArray[2] and someArray[3] are large negative numbers, and subtracting both causes someNumber to roll over to negative.
The loop exits because (someNumber -= someArray[findTheValue]) doesnt set.
Adding a debug line, you can see
value 0 number 97 array 0
value 1 number 96 array 1
value 2 number 1208148276 array -1208148180
that is printing out findTheValue, someNumber, someArray[findTheValue]
Its not the answer I would have expected at first glance.
Checking addresses:
printf("&someNumber = %p\n", &someNumber);
printf("&someArray[0] = %p\n", &someArray[0]);
printf("&someArray[1] = %p\n", &someArray[1]);
printf("&findTheValue = %p\n", &findTheValue);
gave this output:
&someNumber = 0xbfc78e5c
&someArray[0] = 0xbfc78e50
&someArray[1] = 0xbfc78e54
&findTheValue = 0xbfc78e58
It seems that for some reason the compiler puts the array in the beginning of the stack area, then the variables that are declared below and then those that are above in the order they are declared. So someArray[3] effectively points at someNumber.
I really do not know the reason, but I tried gcc on Ubuntu 32 bit and Visual Studio with and without optimisation and the results were always similar.