简体   繁体   English

可以取消对指针的引用吗?

[英]Can dereferencing of pointer throw?

I'm teaching myself techniques of programming with exception safety mode of ;) and I wonder if dereferencing a pointer could ever throw an exception? 我正在自学使用;)异常安全模式进行编程的技术,并且我想知道解除引用指针是否会引发异常? I think it would be helpful for all C++ programmers to know all operations that are guarantied to not throw so I would be very grateful if someone could compose such list. 我认为这对所有C ++程序员了解保证不会抛出的所有操作会有所帮助,因此,如果有人可以编写这样的列表,我将非常感激。

Dereferencing a simple pointer ( T* ) can lead to Undefined Behavior if there is no valid object of the specified type where the pointer points to. 如果没有指向指针的指定类型的有效对象,则取消引用简单指针T* )可能导致未定义行为 It's the nature of UB that the result might be anything , including, but not limited to, a C++ exception. UB的本质是结果可能是任何东西 ,包括但不限于C ++异常。 One could indeed imagine an implementation that would check pointers on access and throw an exception. 确实可以想象有一种实现将检查访问指针并抛出异常。 However, I doubt that such an implementation of C++ will ever exist (if you can spare the runtime overhead of doing this, why use C++?) and the common behavior on most platforms is to either muddle on (if the memory in question is allocated to the process) or crash . 但是,我怀疑这样的C ++实现是否会存在(如果您可以节省这样做的运行时开销,为什么要使用C ++?),并且大多数平台上的常见行为是混淆(如果分配了相关的内存)或崩溃) On some platforms there are ways to intercept such crashes (like Windows' Structured Exceptions ). 在某些平台上,有一些方法可以拦截此类崩溃(例如Windows的“ 结构化异常” )。

However, the unary operator*() might be overloaded , and usually is for smart pointers and iterators. 但是,一元运算operator*()可能会重载 ,通常用于智能指针和迭代器。 Such implementations can certainly do anything their implementors want, including, but not limited to, throwing an exception. 这样的实现当然可以执行其实现者想要的任何事情,包括但不限于引发异常。 But again due to runtime overhead, common smart pointer implementations only check in debug builds (usually using some form of an assertion), but not in release builds. 但同样由于运行时开销,常见的智能指针实现仅在调试版本中(通常使用某种形式的断言)签入,而在发布版本中则不签入。 (A notable exception are the iterators in recent Visual C++ implementations, which do get quite some heat for this unusual behavior.) (一个值得注意的例外是最近的Visual C ++实现中的迭代器,它确实为这种异常行为带来了很大的麻烦。)

There is a very strong tradition in C++ to differentiate between errors the programmer could have prevented (like accessing an array out of bounds) and errors that programmers could not have prevented (like a network connection dying). 在C ++中,有很强的传统来区分程序员可能避免的错误 (例如,超出范围访问数组)和程序员无法避免的错误 (例如网络连接中断)。 For raw speed, the former usually lead to UB , because checking them every time would cost performance. 对于原始速度,前者通常会导致UB ,因为每次检查它们都会降低性能。 It's left to programmers to check where appropriate and necessary. 留给程序员检查是否适当和必要。
You can see this distinction in the definition of the standard library's exception hierarchy, which splits into preventable std::logic_error and unpreventable std::runtime_error . 您可以在标准库的异常层次结构的定义中看到这种区别,该层次分为可预防的std::logic_errorstd::logic_error预防的std::runtime_error

Dereferencing an invalid pointer is undefined behavior, which the implementation can then define as a thrown exception. 取消引用无效的指针是未定义的行为,然后实现可以将其定义为引发的异常。 This is very uncommon in C++, although it's the rule in some other languages. 尽管这是某些其他语言中的规则,但在C ++中很少见。

You can catch memory access exceptions using std::signal( my_handler, SIGSEGV ); 您可以使用std::signal( my_handler, SIGSEGV );捕获内存访问异常std::signal( my_handler, SIGSEGV ); , although that still depends on platform support, and the Standard does not allow you to translate it into a C++ exception. ,尽管这仍然取决于平台支持,并且Standard不允许您将其转换为C ++异常。

I understand that Microsoft has their own "managed" exceptions or some such, which perhaps could be caught with that mechanism and rethrown in C++ conventions. 我知道Microsoft拥有自己的“托管”异常或某些此类异常,也许可以用该机制捕获并在C ++约定中重新抛出。 Or maybe that's forbidden; 也许那是被禁止的; I don't know. 我不知道。

dereferencing occurs at runtime, and at a very low level(assembly/machine level), thus it cannot throw anything, it will however raise and exception, such as EXCEPTION_ACCESS_VIOLATION or SegFault on linux/unix. 解除引用发生在运行时,并且级别很低(程序集/机器级别),因此它不能抛出任何东西,但是会引发异常,例如linux / unix上的EXCEPTION_ACCESS_VIOLATION或SegFault。

(this assumes raw pointers are being used) (这假设正在使用原始指针)

If it's a simple pointer (and not some autopointer object or iterator, etc.) then the act of dereferencing can't throw an exception, because dereferencing on its own doesn't do anything. 如果它是一个简单的指针(而不是某些自动指针对象或迭代器等),则取消引用的行为将不会引发异常,因为取消引用本身不会执行任何操作。 In the compilation process, dereferencing a pointer is just a way of telling the compiler to compose an instruction that does something with what that pointer points to. 在编译过程中,取消引用指针只是告诉编译器编写一条使用该指针指向的内容执行指令的方法。 If the pointer is invalid and you try to write to it with a dereferenced expression, then it certainly will (or should) error out. 如果指针无效,并且您尝试使用取消引用的表达式对其进行写入,则它肯定会(或应该)出错。

As an example: 举个例子:

int *p = 0xFFFFFFFF; // Invalid pointer
*p;                  // Dereferenced, but since it doesn't do anything there's no error
*p = 0;              // Dereferenced write, so it will halt and catch fire

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM