捕获所有类型的断言
Catch all type of assertion
我需要一个条件:
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::vector
和at (size_type n)
方法来获得out_of_range
异常-就像您需要的那样。
- Mat的convertTo函数在OpenCV中将灰度图像的类型转换为CV_32F时抱怨断言错误
- 静态断言 std::array 的大小,其类型是使用 decltype 从成员函数的返回值中获取的
- 断言 sv_count !=0 失败 - 函数 train_auto,SVM 类型 - EPS_SVR
- 如何断言模板参数的类型 STL 迭代器类型
- 围绕静态断言不完整的类型
- C 11多态映射键静态断言失败:哈希函数必须与密钥类型的参数无关
- 实例化时静态断言模板类型的大小
- 如何使用 cppunit 断言宏来检查返回数据类型的预处理器值
- 你能静态断言对象可以转换为某种类型吗?
- 类型没有数据成员的静态断言
- SVM训练错误(样本类型的断言失败)
- 在QML中将null分配给C++类型的QObject*属性时断言失败
- 如何创建一个编译时断言模板是特定类型的?
- 编译时对数据类型大小进行断言
- 捕获所有类型的断言
- c++编译类型资源所有者断言
- 模板类中' is_base_of '的静态断言在MSVC中因类型意外而失败
- c++, google test/mock:测试和对象类型的断言
- 类型比较的Boost静态断言
- 静态断言类型a可以由类型B构造