库实现者如何决定何时抛出异常与展示未定义的行为?

时间:2015-07-24 20:43:57

标签: c++ exception-handling

特别考虑C ++ string类构造函数规范,我们有:

string (const string& str, size_t pos, size_t len = npos);
string (const char* s, size_t n);

除了字符串与c-string之外,它们基本上具有相同的形式/意图。但异常规范却截然不同:

  

如果pos大于str的长度,则out_of_range异常为   抛出。

     

如果n大于s指向的数组,则会导致   未定义的行为。

我想知道为什么会这样?除了性能之外,什么时候抛出异常与允许"未定义的行为?#34 ;?答案似乎取决于以下内容:

  • 客户端能够先验识别故障(即客户端识别文件访问的潜在问题的可能性要小于,比如从客户端明确使用的空堆栈中弹出)
  • 客户对处理潜在问题的兴趣(也许更经常需要处理文件访问问题,因为不太可预测?)
  • 什么"最有意义"从实现者的角度来看(也许是字符串版本抛出,因为它更多地与c ++风格相关联,因此异常语义)

3 个答案:

答案 0 :(得分:3)

两种情况的不同之处仅在于,在第一种情况下,实现中可能检查传递的参数是否存在错误,而在第二种情况下< em>不可能(没有办法检查字符串的长度,因为只传递了一个指针)。

所以一般规则如下:

  1. 如果可能,请检查可能的失败情况并提出异常;
  2. 否则,从实施者的角度来看,没有什么可以做的,并且在功能文档的规范中可能会出现未定义的行为。

答案 1 :(得分:2)

库实现者必须实现C ++标准规定的行为,并且C ++标准指定:

basic_string(const basic_string& str,
             size_type pos, size_type n = npos,
             const Allocator& a = Allocator());
  

需要:pos&lt; = str.size()
  抛出:out_of_range如果pos&gt; str.size()。

的情况下
basic_string(const charT* s, size_type n,
             const Allocator& a = Allocator());

标准只是说:

  

要求:s指向至少n个charT元素的数组。

(全部来自§21.4.2[string.cons])

由于标准没有规定在第二种情况下发生的情况如果不满足要求,那就是未定义的行为,让库实现自由地做它想做的任何事情。但是,库无法实际检测到未满足要求的事实,因此可以自由地假设满足要求,然后让程序以硬件对读取无效地址的任何反应中断。

如果您正在寻求理由,您应该寻求标准的理由。图书馆实施者几乎没有灵活性。

答案 2 :(得分:1)

您示例中的行为原因非常明显。

  • 在第一种情况下,复制的字符串的大小是已知的,它是对象的属性之一。根据它来检查其他参数很简单。
  • 在第二种情况下,你只有一个指针。通常,您无法说出相应的内存区域有多大。因此,您无法检查其他参数是否正确。