Nor*_*ame 11
有基于运行时的解决方案,用于检测代码以检查无效指针访问.到目前为止我只使用过mudflap(自4.0版以来就集成在GCC中).mudflap尝试跟踪代码中的每个指针(和引用),如果指针/引用实际指向其基类型的活动对象,则检查每次访问.这是一个例子:
#include <stdio.h>
struct S {
S(int & value): value_(value) {}
int & value_;
};
S function() {
int value = 0;
return S(value); // implicitly returning reference to local value
}
int main()
{
S x=function();
printf("%s\n",x.value_); //<-oh noes!
}
Run Code Online (Sandbox Code Playgroud)
在启用mudflap的情况下编译它:
g++ -fmudflap s.cc -lmudflap
Run Code Online (Sandbox Code Playgroud)
并且运行给出:
$ ./a.out
*******
mudflap violation 1 (check/read): time=1279282951.939061 ptr=0x7fff141aeb8c size=4
pc=0x7f53f4047391 location=`s.cc:14:24 (main)'
/opt/gcc-4.5.0/lib64/libmudflap.so.0(__mf_check+0x41) [0x7f53f4047391]
./a.out(main+0x7f) [0x400c06]
/lib64/libc.so.6(__libc_start_main+0xfd) [0x7f53f358aa7d]
Nearby object 1: checked region begins 332B before and ends 329B before
mudflap object 0x703430: name=`argv[]'
bounds=[0x7fff141aecd8,0x7fff141aece7] size=16 area=static check=0r/0w liveness=0
alloc time=1279282951.939012 pc=0x7f53f4046791
Nearby object 2: checked region begins 348B before and ends 345B before
mudflap object 0x708530: name=`environ[]'
bounds=[0x7fff141aece8,0x7fff141af03f] size=856 area=static check=0r/0w liveness=0
alloc time=1279282951.939049 pc=0x7f53f4046791
Nearby object 3: checked region begins 0B into and ends 3B into
mudflap dead object 0x7089e0: name=`s.cc:8:9 (function) int value'
bounds=[0x7fff141aeb8c,0x7fff141aeb8f] size=4 area=stack check=0r/0w liveness=0
alloc time=1279282951.939053 pc=0x7f53f4046791
dealloc time=1279282951.939059 pc=0x7f53f4046346
number of nearby objects: 3
Segmentation fault
Run Code Online (Sandbox Code Playgroud)
需要考虑的几点:
PS要考虑的一件事是,在S()的复制构造函数中添加一个NON-PORTABLE检查,它断言value_没有绑定到寿命较短的整数(例如,如果*这位于"旧的"堆栈的插槽,它绑定的整数).这是高度机器特定的,当然可能很难得到,但只要它只用于调试就应该没问题.
我认为这不可能捕获所有这些,尽管某些编译器在某些情况下可能会发出警告。
还要记住,引用实际上是引擎盖下的指针,并且指针可能实现的许多射击自足场景仍然可行。
为了阐明我对“引擎盖下的指针”的含义,参加以下两节课。一个使用引用,另一个使用指针。
class Ref
{
int &ref;
public:
Ref(int &r) : ref(r) {};
int get() { return ref; };
};
class Ptr
{
int *ptr;
public:
Ptr(int *p) : ptr(p) {};
int get() { return *ptr; };
};
Run Code Online (Sandbox Code Playgroud)
现在,比较两者的生成代码。
@@Ref@$bctr$qri proc near // Ref::Ref(int &ref)
push ebp
mov ebp,esp
mov eax,dword ptr [ebp+8]
mov edx,dword ptr [ebp+12]
mov dword ptr [eax],edx
pop ebp
ret
@@Ptr@$bctr$qpi proc near // Ptr::Ptr(int *ptr)
push ebp
mov ebp,esp
mov eax,dword ptr [ebp+8]
mov edx,dword ptr [ebp+12]
mov dword ptr [eax],edx
pop ebp
ret
@@Ref@get$qv proc near // int Ref:get()
push ebp
mov ebp,esp
mov eax,dword ptr [ebp+8]
mov eax,dword ptr [eax]
mov eax,dword ptr [eax]
pop ebp
ret
@@Ptr@get$qv proc near // int Ptr::get()
push ebp
mov ebp,esp
mov eax,dword ptr [ebp+8]
mov eax,dword ptr [eax]
mov eax,dword ptr [eax]
pop ebp
ret
Run Code Online (Sandbox Code Playgroud)
指出不同?没有
| 归档时间: |
|
| 查看次数: |
3731 次 |
| 最近记录: |