swicano
swicano

Reputation: 85

Need help tracking down an illegal write. valgrind not noticing it

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

Upvotes: 1

Views: 881

Answers (3)

Employed Russian
Employed Russian

Reputation: 213375

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.

Upvotes: 2

Roland
Roland

Reputation: 6543

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.

Upvotes: 1

Michael Burr
Michael Burr

Reputation: 340168

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.

Upvotes: 2

Related Questions