使用对0指针的解引用是危险的



考虑以下示例:

   // someLibrary.h  which is exported.
    struct HandlePrivate;
    typedef HandlePrivate&  Handle; 
    Handle getHandle(int code);
    void closeHandle(Handle handle);

   // someLibrary.cpp
   #include "someLibrary.h"
   struct HandlePrivate{};//definition of HandlePrivate;
   Handle getHandle(int code)
   {
        static HandlePrivate instance;
        return  code >= 0 
                ? instance 
                :  ( *(HandlePrivate*)0); // Hack, I know it's UB.
   }

现在,其他程序员使用这个库:

    // userSource.cpp
    #include "someLibrary.h"
    void foo(int code)
    {
        Handle h = getHandle(code);
        // some user code
       closeHandle(h);
    }

问题:如果"SomeLibrary"作者使用该hack (UB),何时可能会破坏用户代码(崩溃或其他糟糕的东西)?

如果用户只使用Windows和Visual Studio 2010,答案会改变吗?

因为,下面的例子没有崩溃!!:

#include <functional>
#include <type_traits>
#include "someLibrary.h"
void foo(int code)
{
     typedef std::reference_wrapper< std::remove_reference<Handle>::type> reference;
     reference h = getHandle(code);
     closeHandle(h); // is not crash, if code = -1     !!!!!!!!!!  

//但是,std::reference_wrapper::operator &() -对指向0的指针解引用。}

当指针被设置为0时,它指向地址为0的对象。地址可以是物理地址0或逻辑地址(相对于您的用户空间)。

对指向0的指针解引用的唯一情况是,当地址0有内存,并且地址0可以被应用程序访问(一些操作系统不允许访问各种地址)。

例如,在某些嵌入式系统中,地址0是一个包含启动程序地址的向量。要读取地址向量的值,必须赋值一个值为0的指针,并对其解引用。

使用空指针访问对象的方法是未定义的行为。如果该方法不使用任何数据成员,您可能会很幸运。如果方法使用数据成员,则该方法期望这些数据成员位于地址0附近。

如果你想在不创建对象实例的情况下访问对象方法,那么将这些方法声明为static

相关内容

  • 没有找到相关文章

最新更新