为什么 STL 实现不使用断言来检测未定义的行为?
Why do STL implementations not use assertions to detect undefined behaviour?
我觉得这可能会有用,但我还没有在 gcc 的标准库中看到它的实现。
基本上,在我看来,STL 实现可以添加断言来检测(在运行时)简单的错误,例如越界访问。我猜这些访问无论如何都是标准中未定义的行为,所以肯定会打印一条错误消息并且 - 可选地 - 中止将符合标准。
这些断言当然可以在编译时通过旧的 NDEBUG 标志或其他一些标志关闭。
作为一个小例子,我希望这段代码中止:
#include <vector>
int main()
{
return std::vector<int>{1,2}[2];
}
顺便说一句,我完全知道像 valgrind 这样的工具的存在,但这可能是一个额外的好处。此外,像 valgrind 这样的内存检查工具不能保证检测到某些错误,例如在向量大小缩小后访问越界元素,因为实现可能不会立即重新分配底层内存。
This is something that I feel could come in useful but that I have not seen implemented in gcc's standard library.
你错了,尝试定义 _GLIBCXX_DEBUG
,这会使你的示例中止:
/home/jwakely/gcc/5/include/c++/5.0.0/debug/vector:402:error: attempt to
subscript container with out-of-bounds index 2, but container only
holds 2 elements.
Objects involved in the operation:
sequence "this" @ 0x0x7fffb8b221a0 {
type = NSt7__debug6vectorIiSaIiEEE;
}
Aborted (core dumped)
These assertions could of course be turned off at compile time through the old NDEBUG flag or some other flag.
之所以使用单独的机制而不是 assert()
和 NDEBUG
,是因为检查会增加开销,因此只有在明确请求时才启用。这意味着用户可以继续使用 assert()
进行自己的检查,而无需打开标准库检查的开销。由于用于跟踪迭代器有效性的附加数据成员,还存在需要注意 libstdc++ 调试模式的二进制兼容性问题。有关详细信息,请参阅 https://gcc.gnu.org/onlinedocs/libstdc++/manual/debug_mode.html。
Libc++ 也有类似的检查,使用不同的宏,VC++ 在调试版本中自动启用类似的检查。
我觉得这可能会有用,但我还没有在 gcc 的标准库中看到它的实现。
基本上,在我看来,STL 实现可以添加断言来检测(在运行时)简单的错误,例如越界访问。我猜这些访问无论如何都是标准中未定义的行为,所以肯定会打印一条错误消息并且 - 可选地 - 中止将符合标准。
这些断言当然可以在编译时通过旧的 NDEBUG 标志或其他一些标志关闭。
作为一个小例子,我希望这段代码中止:
#include <vector>
int main()
{
return std::vector<int>{1,2}[2];
}
顺便说一句,我完全知道像 valgrind 这样的工具的存在,但这可能是一个额外的好处。此外,像 valgrind 这样的内存检查工具不能保证检测到某些错误,例如在向量大小缩小后访问越界元素,因为实现可能不会立即重新分配底层内存。
This is something that I feel could come in useful but that I have not seen implemented in gcc's standard library.
你错了,尝试定义 _GLIBCXX_DEBUG
,这会使你的示例中止:
/home/jwakely/gcc/5/include/c++/5.0.0/debug/vector:402:error: attempt to
subscript container with out-of-bounds index 2, but container only
holds 2 elements.
Objects involved in the operation:
sequence "this" @ 0x0x7fffb8b221a0 {
type = NSt7__debug6vectorIiSaIiEEE;
}
Aborted (core dumped)
These assertions could of course be turned off at compile time through the old NDEBUG flag or some other flag.
之所以使用单独的机制而不是 assert()
和 NDEBUG
,是因为检查会增加开销,因此只有在明确请求时才启用。这意味着用户可以继续使用 assert()
进行自己的检查,而无需打开标准库检查的开销。由于用于跟踪迭代器有效性的附加数据成员,还存在需要注意 libstdc++ 调试模式的二进制兼容性问题。有关详细信息,请参阅 https://gcc.gnu.org/onlinedocs/libstdc++/manual/debug_mode.html。
Libc++ 也有类似的检查,使用不同的宏,VC++ 在调试版本中自动启用类似的检查。