捕获所有类型的断言

Catch all type of assertion

本文关键字:断言 类型      更新时间:2023-10-16

我需要一个条件:

try
{
//bug condition
}
catch()
{
//Remove file
}

也就是说,我创建了一个非常机密的文件,其中的数据不能被第三方查看,但是当代码中出现任何错误时,我的文件被删除,因为我不知道错误发生在哪里。

我想用try和catch捕获那个bug,然后删除那个文件。我如何在c++中捕获任何异常?

如果有错误,将删除文件。

:

try
{
    char TempArray[10];
    char c = TempArray[11];
}
catch
{
    cout<<"Array out of boundry";
    deleteFile("Confi.txt");
}

关于安全的一句话:如果你在硬盘上创建了一个包含机密信息的文件,任何人都可以在程序运行时关闭计算机,而文件仍处于打开状态,取出硬盘并读取其内容。

如果文件在服务器上,您可以在删除文件之前暂停进程,从而完成基本相同的操作。

即使您从文件系统中删除了这个文件,很可能它仍然可以被读取,因为删除一个文件并不会擦除它的内容。

我建议在你拥有所需的专业知识之前不要处理机密信息——而不是通过向SO学习。但如果你必须这样做,我认为这里建议的看门狗过程+加密是可行的。

首先:

你不会想那样做的。

异常不是为了处理bug ,而是运行时的错误条件,使你的函数不可能满足它必须调用的其他函数的前提条件,或者保证满足它自己的后处理条件(假设调用者已经满足了前提条件)。例如,请看Herb Sutter的这篇文章。

永远不要写这样的东西:

try
{
    //bug condition <== NO! Exceptions are not meant to handle bugs
}
catch()
{
    //Remove file
}

而是:

assert( /* bug condition... */ );

回到问题:

你的程序有未定义的行为,当你这样做的时候,很可能它根本不会抛出任何异常:

char TempArray[10];
char c = TempArray[11];

所以捕获所有异常是没有帮助的。这是一个bug,即一个编程错误,你是否应该以一种将控制转移到有bug的例程的方式来处理bug是有争议的;此外,如果您承认程序中存在错误,您就不能将控制权转移给错误处理程序吗?那可能会使情况更糟。

应该通过防止错误,使用断言,或者采用诸如测试驱动开发等方法来处理

错误。

也就是说,关于捕获所有异常的方法,你可以这样做:

try
{
    // ...
}
catch (...) // <== THIS WILL CATCH ANY EXCEPTION
{
}

但是不鼓励使用catch (...)作为设计指南,因为它很容易导致吞下应该处理的错误条件并忘记它们。毕竟,异常的发明正是为了防止程序员忘记检查错误代码,而catch (...)使这一点变得如此容易。

为了捕获一切的目的,最好让所有的异常都来自std::exception,然后做:

try
{
    // ...
}
catch (std::exception& e)
{
    // Do something with e...
}

您要使用的是RAII。在这种情况下,创建一个类,在构造函数中取文件名,在析构函数中删除文件。在对文件进行任何操作之前,您用适当的名称实例化此类对象,然后如果由于某种原因函数退出(干净地或通过异常的方式),该文件将被删除。

示例代码:

class FileGuard : public boost::noncopyable {
    std::string filename_;
    public:
    FileGuard(const std::string &filename) : filename_(filename)
    {}
    ~FileGuard()
    {
        ::unlink(filename_);
    }
 }

您的代码试图访问定义边界之外的数据,这在本质上是一个完全有效的尝试。根据情况和编译器,您的代码可能会或可能不会因访问冲突/段错误而崩溃,但很可能不会。它肯定不会引发异常——在c++中,异常只由代码显式抛出,而不是由系统隐式抛出,如果出错,它只会崩溃,这与Java和c#等高级语言不同。

catch(...)语法将捕获所有可能的异常,但这在这种情况下不适用。

正如其他答案所暗示的那样,您无法使用本机标准c++正确解决此问题。事实上,一旦undefined behaviour发生,试图做任何事情通常是一件非常糟糕的事情。如果你不知道你的应用程序所处的状态,你怎么可能安全地运行代码?快失败吧。

解决问题的正确方法是让另一个独立的"看门狗"进程执行清理。这很简单——只要让看门狗进程不断地监视文件的存在。当它突然出现时,看门狗进程应该删除它。这个删除将一直持续到最后一个对文件的引用存在,然后它将执行删除[在*nix操作系统上,它将重命名文件到一个临时位置,在Win系统上,它将一直等到文件不被引用]。一旦主程序处理完文件——无论是通过正常方式还是崩溃或其他方式,操作系统将为您正确删除文件。

如果你想确保你的'私有'文件总是被删除,那么一个'包装'程序如何?

创建一个新的应用程序,运行受保护的应用程序,然后等待它终止。当它终止时(无论是崩溃还是清理退出),删除您的私有文件,然后退出。

不要运行应用程序,而是运行包装器。

int main(void)
{
    int processId = exec("your protected app");
    WaitForProcessExit(processId);
    _unlink("protectedfile.bin");
    return 0;           
}

c++允许您直接使用内存,并且部分与C兼容。您要使用的语法:

char some_array[10];

有点像C语法,而不是c++和

char c = some_array[11];

是对内存的原始访问。这是unexpected behavior。这意味着没有人会告诉你将会发生什么。也许你只是输入了错误的字符,也许你的程序会被操作系统杀死。否则月球就会落到地球上。=)

如果你想要高级功能-使用纯c++。查看标准库而不是"C"数组。您可以使用std::vectorat (size_type n)方法来获得out_of_range异常-就像您需要的那样。