【问题标题】:Preventing local pointers防止本地指针
【发布时间】:2012-06-13 04:34:30
【问题描述】:

也许这是一个新手问题,但是 C/C++ 中有没有一种方法可以防止函数接受指向局部变量的指针?

考虑这段代码:

int* fun(void)
{
 int a;
 return &a;
}

编译器会产生一个指针不能返回的警告。现在考虑一下:

int* g;

void save(int* a)
{
 g = a;
}

void bad(void)
{
 int a;
 save(&a);
}

这将在没有警告的情况下通过编译器,这很糟糕。是否有属性或东西可以防止这种情况发生? IE。类似:

void save(int __this_pointer_must_not_be_local__ * a)
{
 g = a;
}

如果有人知道答案,请提前感谢。

【问题讨论】:

  • 代码审查? ...代码分析器,例如 lint?
  • 代码审查,静态分析。您所要求的实际上非常非常复杂。
  • 如果我想做void f() { int b; save(&b); /* do stuff */ save(NULL); } 怎么办?变量是“本地”的事实并不一定很重要。这也会很糟糕。 int* p = new int(); save(p); delete p;
  • @CharlesBailey:有很多不好的地方; OP 正在询问一个特定的问题,编译器似乎已经能够识别它(用于警告返回本地指针的逻辑)。
  • @ScottHunter:我的意思是存储指向本地对象的指针不一定是坏事。将其标记为错误会产生误报。

标签: c pointers compiler-warnings


【解决方案1】:

至少有一种使用调试堆调试构建的方法(默认):

//d:\Program Files\Microsoft Visual Studio ?\VC\crt\src\dbgint.h
\#define nNoMansLandSize 4
typedef struct _CrtMemBlockHeader
{
    struct _CrtMemBlockHeader * pBlockHeaderNext;
    struct _CrtMemBlockHeader * pBlockHeaderPrev;
    char *                      szFileName;
    int                         nLine;
    size_t                      nDataSize;
    int                         nBlockUse;
    long                        lRequest;
    unsigned char               gap[nNoMansLandSize];
    /* followed by:
     *  unsigned char           data[nDataSize];
     *  unsigned char           anotherGap[nNoMansLandSize];
     */
} _CrtMemBlockHeader;
\#define pbData(pblock) ((unsigned char *)((_CrtMemBlockHeader *)pblock + 1))

有一个分配头,以gap结尾,所以指针前有0xFDFDFDFD的可能性不大-不完美,但可能有帮助...

if (\*((int\*)pointer-1) == 0xFDFDFD) { // stack pointer }

【讨论】:

    【解决方案2】:

    不,没有可靠且可移植的方法来区分指向本地的指针和指向堆对象的指针。也没有办法以声明方式防止这种情况发生。

    有一些依赖于特定系统的内存布局的 hack,它们在运行时通过调用未指定的行为来工作(请参阅 this answer 以获取示例),但如果您决定尝试它们,则只能靠自己。

    【讨论】:

    • 但是,如果编译器能够识别出函数何时尝试返回本地指针,并且如果存在 OP 建议的属性,为什么编译器不能使用相同的逻辑来生成警告?
    • @ScottHunter 因为编译器无法通过静态分析代码来可靠地确定它。将指针存储在全局变量中只是绕过检查的一种方法 - 您可以将其存储在结构成员中,转换为字节数组,等等。添加如此不可靠的检查会破坏目的。
    • 这与实施的退货检查有何不同?
    • @Scott。因为编译器知道“return”之后返回的指针将不再有效。在其他情况下,它根本无法可靠地确定指针是否将在函数结束后使用。结果将是对误报的无用警告(人们很快就会开始忽略)或错过案例(这会破坏目的)。为了避免在脚上射击,正确瞄准比在指向下方时枪不工作要好得多。
    猜你喜欢
    • 1970-01-01
    • 2022-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-15
    • 2012-10-27
    • 2014-08-02
    • 2018-10-25
    • 2020-04-07
    相关资源
    最近更新 更多