Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
捕捉奇怪的C指针算法错误_C_Pointers_Findbugs - Fatal编程技术网

捕捉奇怪的C指针算法错误

捕捉奇怪的C指针算法错误,c,pointers,findbugs,C,Pointers,Findbugs,我最近遇到了一个非常隐蔽的错误,在这个错误中,我忘记了取消对字符串(字符数组)的引用,因此有时会在堆栈上重写一个字节 坏的: 更正: char ** str; (*str) = malloc(10); ... (*str)[2] = 'a'; GCC没有产生任何警告,这个错误会导致非常严重和真实的攻击,因为它有时重写的值具有缓冲区的大小。我抓住这个错误是因为我运气好,它导致了明显的失败 除了依靠运气和/或从不使用C做任何事情之外,您使用什么防御性编码技术和技巧来捕获wierd C bug

我最近遇到了一个非常隐蔽的错误,在这个错误中,我忘记了取消对字符串(字符数组)的引用,因此有时会在堆栈上重写一个字节

坏的:

更正:

char ** str;
(*str) = malloc(10);
...
(*str)[2] = 'a'; 
GCC没有产生任何警告,这个错误会导致非常严重和真实的攻击,因为它有时重写的值具有缓冲区的大小。我抓住这个错误是因为我运气好,它导致了明显的失败

  • 除了依靠运气和/或从不使用C做任何事情之外,您使用什么防御性编码技术和技巧来捕获wierd C bug

  • 我在考虑搬到瓦尔格兰德,有人用过吗?我怀疑它不会抓住这个虫子。有人知道吗

  • 是否有捕捉指针解引用或算术错误的工具?这可能吗

更新 下面是请求的示例代码,它不会抛出任何警告

#include <stdlib.h>

void test(unsigned char** byteArray){
    (*byteArray) = (unsigned char*)malloc(5);
    byteArray[4] = 0x0;
}

int main(void){
    unsigned char* str;
    test(&str);  
    return 0;
}
运行会导致seg故障:

./testBug
Segmentation fault
这是我正在使用的GCC版本:

gcc -v

Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.4.1-4ubuntu9' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-targets=all --disable-werror --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
Thread model: posix
gcc version 4.4.1 (Ubuntu 4.4.1-4ubuntu9) 

我用Valgrind,它是救命稻草

valgrind --tool=memcheck -v ./yourapp
MemCheck将检测到您有一个'str[2]='a'的无效写入;'.

GCC应该给您

 warning: assignment makes pointer from integer without a cast

否?

我的最佳防御指针策略:强烈避免使用多个级别的间接寻址。取消对指针的引用以为其分配内存是正常的。但是,然后将分配的内存用作数组是自找麻烦的,这是您得到的。我会把它做成这样:

char **outStr;
*outStr = malloc(10);
char *str = *outStr;
str[2] = 10;

好吧,实际上这只是一个保持理智的策略,碰巧也有防御价值。当一次不存在超过一个级别的间接寻址时,指针是相当容易理解的,而当您很好地理解它时,使代码正常工作就更容易了。

我的建议不是一种工具,而是一种最佳实践:测试。这样的错误通常很容易通过严格的代码测试发现,从最低级别的单元测试开始

您展示的代码永远不会产生正确的结果-它不是有时有效,有时无效的东西。对这段代码进行单元测试可以节省以后与系统其他部分集成时的调试时间


单元测试可以通过覆盖率检查来补充:要么使用自动工具,要么只是手动扫描代码并编写针对每个部分的测试-这实际上是重新读取代码(另一个调试工具)的好方法,效果惊人。

请使用Valgrind。这是我遇到的最好的内存检查工具之一。它肯定会发现你的错误

除了检测内存错误,valgrind还帮助检测内存泄漏、正在使用的内存块等


甚至可以帮助您检测此类错误。虽然我个人最喜欢的是Valgrind。

这样做会给我一个警告:“警告:赋值从整数生成指针而不进行强制转换”。@jefrom我尝试了我刚刚发布的内容,但我肯定没有收到警告。我也在使用-Wall进行编译。您的示例代码分配的是
0x0
,而不是初始问题描述中的
'a'
。编译器不会对赋值0发出警告,因为它是空指针常量。编辑:哦,R Samuel Klatchko已经在另一个帖子中说过了……我的评论提到了你的原始代码,这肯定会产生警告。遗憾的是,我没有收到这样的错误。当我遇到这个错误时,我修复了gcc生成的唯一警告。@e5您使用的是什么版本的gcc?它确实给了我警告。gcc 4.4.1,我刚刚测试过,它没有给出任何警告。代码如下:无符号字符**str;(str)=(char)malloc(5);str[5]=0x0;可能是因为我正在将(char*)强制转换为无符号char*?@e5-这不会给您一个警告,因为0x0既是一个有效的整数,也是一个有效的指针。更改
str[5]=0x0
str[5]=“a”查看警告。+1@R塞缪尔·克拉奇科你说得对!做得好。我想将最后一个字符设置为NULL,因为它是以NULL结尾的字符串。如何以安全的方式做到这一点?我完全同意一个好的测试代码会有很大帮助。但是,在好的测试代码上运行valgring将仔细检查您的代码并使其保持完美。Unittesting很棒,我完全支持它,但它可能不会捕获此错误,因为只有在集成两个组件(单元)时,此错误才可见。此外,如果覆盖值增加而不是减少覆盖值,则不会激活任何故障模式。
 warning: assignment makes pointer from integer without a cast
char **outStr;
*outStr = malloc(10);
char *str = *outStr;
str[2] = 10;