【问题标题】:How to catch exception when write to a random memory block in c++在 C++ 中写入随机内存块时如何捕获异常
【发布时间】:2013-03-03 18:23:03
【问题描述】:
int main()
{
    int *a; // a = 0x4053c6 (a random address)
    // this will cause the program to exit, and how do i know this memory can't be written ?
    *a = 5;
    return 0;
}

困惑!我的意思是这个 sn-p 是否总是导致程序崩溃?还有这个程序可以从头到尾执行的情况吗?

【问题讨论】:

  • 您必须自己跟踪。在这种情况下,您知道 a 未初始化,因此读取该指针值是未定义的行为(更不用说写入其延迟位置)。
  • 我知道a 未初始化。大多数编译器会报告警告。但是,我想知道*a = 5 是否有机会执行。
  • @Ggicci:是的,有机会 - 未定义的行为意味着任何事情都可能发生。如果可能是巧合,a 持有例如它自己的地址和*a 因此是一个有效的写入位置(据限制程序的操作系统所知)。尽管如此,如果a 碰巧拥有自己的地址,但不能保证它会起作用……对于未定义的行为,没有任何保证。还有其他无害的可能性 - 例如。 a 可以轻松指向一些当前未使用的堆栈空间。
  • @Cgicci - 如果您编写愚蠢的代码,预计会发生愚蠢的事情。只需编写代码并确保不会发生内存泄漏。使用编译器警告、purify/valgrid 和测试等应用程序。
  • @GManNickG,这不是 C++ 异常,而是陷阱 (SEH)。一些系统将这些称为异常 (Windows)。

标签: c++ exception memory-leaks


【解决方案1】:

它通常会导致崩溃,但不能保证(因为变量未初始化,它可以包含任何值,有效或无效)。您无法通过 C++ 异常捕获访问冲突,但编译器提供了扩展来执行此操作。例如,在 Visual C++ 中,您可以使用 SEH(结构化异常处理):

#include <Windows.h>
#include <iostream>

using namespace std;

int main()
{
    int* p = reinterpret_cast<int*>(0x00000100);

    __try
    {
        *p = 10;
    }
    __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
    {
        cout << "Access violation" << endl;
        return -1;
    }

    cout << *p << endl;
}

【讨论】:

    【解决方案2】:

    代码将出现 Segfault / 访问冲突,根据操作系统将其作为陷阱或信号处理。您可能能够处理它,但之后您不太可能能够做很多事情。 (处理后通常的做法是优雅退出)。

    至于确定有一个案例,要证明它是相当困难的。您可以拥有自己的编译器,将未初始化的变量设置为堆栈上的特定地址,例如(讽刺)。

    伪初始化 a 中的值的一种方法是调用函数:

    void func(int k)
    {
        int *a;
        int b = 0;
        if (k == 1) {
            a = &b;
        }
        *a = 5;
    }
    

    您可以尝试使用 func(1) 几次,然后再尝试 func(2)。有机会 a 和 b 将重用相同的堆栈区域并且不会失败。但这也是一个机会

    【讨论】:

      猜你喜欢
      • 2011-12-06
      • 2015-12-08
      • 2012-08-10
      • 1970-01-01
      • 2021-05-23
      • 1970-01-01
      • 2019-11-24
      • 1970-01-01
      • 2011-01-26
      相关资源
      最近更新 更多