简体   繁体   English

Valgrind for C program report报告令人难以置信的无效写入

[英]Valgrind for C program reporting unbelievable invalid write

Anyone have problems with Valgrind incorrectly reporting an invalid write? 任何人都有Valgrind错误报告无效写入的问题? I've got a C program with this loop: 我有一个带有这个循环的C程序:

void myfunc4(int *myData, ...) 
{
 int *variable1, *variable2, ii, ss, bb, jj;
 ...
 bb = 0;
 for (ii=0; ii<ss; ii++) {  
   for (jj=0; jj<(variable2[ii]-variable1[ii]+1); jj++) {
       myData[bb] = variable1[ii] + jj; /* valgrind reports error is on this line */
       bb = bb+1;
   }
   printf("ss = %d, ii = %d, bb = %d \n", ss, ii, bb);
 }
}

I run Valgrind using, 我用Valgrind跑,

valgrind --log-file=./logfile --leak-check=full ./myProgram

and the first and only "Invalid" error it lists is: 它列出的第一个也是唯一的“无效”错误是:

==6135== Invalid write of size 4
==6135==    at 0x4090AA: myfunc4 (myfunc4.c:170)
==6135==    by 0x408527: myfunc3 (myfunc3.c:168)
==6135==    by 0x406CA1: myfunc2 (myfunc2.c:84)
==6135==    by 0x410163: myfunc1 (myfunc1.c:133)
==6135==    by 0x413726: main (myProgram.c:511)
==6135==  Address 0x1077c250 is 209,712 bytes inside a block of size 209,715 alloc'd
==6135==    at 0x4A05FDE: malloc (vg_replace_malloc.c:236)
==6135==    by 0x408248: myfunc3 (myfunc3.c:119)
==6135==    by 0x406CA1: myfunc2 (myfunc2.c:84)
==6135==    by 0x410163: myfunc1 (myfunc1.c:133)
==6135==    by 0x413726: main (myProgram.c:511)
==6135== 
==6135== More than 10000000 total errors detected.  I'm not reporting any more.
==6135== Final error counts will be inaccurate.  Go fix your program!

Valgrind states the error occurs in the line of code: Valgrind声明错误发生在代码行中:

myData[bb] = variable1[ii] + jj;

If I step through the program at that point using gdb, it runs fine. 如果我使用gdb在那一步完成程序,它运行正常。 The last printf displayed before the loop completes is: 循环完成之前显示的最后一个printf是:

ss = 687, ii = 686, bb = 2690

I can't seem to observe any problem outside of Valgrind. 我似乎无法观察到Valgrind以外的任何问题。 Valgrind consistently gives this error, but gdb consistently shows no problem. Valgrind一直给出这个错误,但gdb始终没有问题。

The memory allocated for myData is, as Valgrind correctly reports, 209712 bytes, which is room for 209712/4 = 52428 integers (I'm using Linux 64 bit machine). 正如Valgrind正确报告的那样,为myData分配的内存是209712字节,这是209712/4 = 52428整数的空间(我使用的是Linux 64位机器)。 From the printf statement, I can see the for loop exits with bb=2690 as it should. printf语句中,我可以看到for循环以bb = 2690退出。 So the largest index used for array myData[bb] (where Valgrind complains) is myData[2689] . 所以用于数组myData[bb]的最大索引(Valgrind抱怨)是myData[2689]

Can anyone shed some light where I can look next? 任何人都可以在我可以看到的地方找到一些亮点? I've been staring at this all day. 我一整天都在盯着这个。 I've not used Valgrind much, and I don't want to call it a lier, but am I doing something wrong here? 我没有多多使用Valgrind,我不想把它称为lier,但我在这里做错了吗? Any advice much appreciated. 任何建议都非常感谢。

UPDATE 1 更新1

The call to myfunc4() inside myfunc3() is: 要将呼叫myfunc4()myfunc3()是:

int *myData, lengthA; 
...
myData = malloc( sizeof(int) * lengthA / 10); 
myfunc4(myData);

UPDATE 2 更新2

If I modify the loop to include an if (bb>10000) statement, gdb never tests true, but Valgrind does. 如果我修改循环以包含if (bb>10000)语句,gdb永远不会测试true,但是Valgrind会这样做。 The compiled program is the same. 编译后的程序是一样的。 Anyone have any insight what's going on? 任何人都有任何洞察力发生了什么?

void myfunc4(int *myData, ...) 
{
 int *variable1, *variable2, ii, ss, bb, jj;
 ...
 bb = 0;
 for (ii=0; ii<ss; ii++) {  
   for (jj=0; jj<(variable2[ii]-variable1[ii]+1); jj++) {
       myData[bb] = variable1[ii] + jj; 
       bb = bb+1;
       if (bb>10000) {
          printf("bb=%d \n", bb); /* valgrind executes this line but gdb does not */
          exit(1);
       }
   }
   printf("ss = %d, ii = %d, bb = %d \n", ss, ii, bb);
 }
}

I finally figured out the bug. 我终于找到了这个bug。 Malloc, of course, doesn't initialize to zero, and I had an if statement (not shown above) that set some array values, but there wasn't a else statement to catch the other path to set the same array values, so that other path used the unitialized values which led to bad behavior. 当然,Malloc没有初始化为零,我有一个if语句(上面没有显示)设置了一些数组值,但是没有else语句来捕获另一个路径来设置相同的数组值,所以其他路径使用了导致不良行为的单一化值。

In this debugging effort, gdb did a better job initializing arrays to zero (via malloc) compared to Valgrind. 在这个调试工作中,与Valgrind相比,gdb在将数组​​初始化为零(通过malloc)方面做得更好。 Not that one should rely on that, but that appears to be the difference between results obtained with gdb and Valgrind here, at least. 不应该依赖于那个,但这似乎是至少在gdb和Valgrind获得的结果之间的差异。

Get the actual number of bytes allocated for the data and pass it to the function: 获取为数据分配的实际字节数并将其传递给函数:

size_t szData = sizeof(int) * lengthA / 10; 
myData = malloc(szData);
myfunc4(myData, szData);

and check the access to verify valgrind: 并检查访问以验证valgrind:

/* .... */
assert((bb +1) * sizeof(int) < szData);
myData[bb] = variable1[ii] + jj;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM