c++ - libc++ std::istringstream 不会抛出异常。漏洞?

标签 c++ language-lawyer libc++

在配置 std::istringstream 以在设置 failbit 时抛出异常后,我在 libc++ 中没有发生任何异常(这是在 linux 下,在 libcxxrt 的支持下编译的 libc++ ).我想这是 libc++ 或 libcxxrt 中的错误:

#include <iostream>
#include <sstream>

template<typename T> std::istream &getvalue(std::istream &is, T &value, const T &default_value = T())
{
    std::stringstream ss;
    std::string s;
    std::getline(is, s, ',');
    ss << s;
    if((ss >> value).fail())
        value = default_value;
    return is;
}

int main()
{
    std::string s = "123,456,789";
    std::istringstream is(s);
    unsigned n;

    try
    {
        is.exceptions(std::ios::failbit | std::ios::eofbit);

        getvalue(is, n);
        std::cout << n << std::endl;

        getvalue(is, n);
        std::cout << n << std::endl;

        // Disable EOF exception on last bit
        is.exceptions(std::ios::failbit);

        getvalue(is, n);
        std::cout << n << std::endl;

        // Force Fail reading after EOF
        getvalue(is, n);
        std::cout << n << std::endl;
    }
    catch(std::ios::failure &fail)
    {
        std::cout << "Fail" << std::endl;
    }
}

libstdc++ 的输出:

123
456
789
Fail

libc++/libcxxrt 输出:

123
456
789
0

编辑

还在 OS X 上进行了测试。

错误提交:http://llvm.org/bugs/show_bug.cgi?id=15949

最佳答案

libc++ 正在响应 27.7.2.1 [istream]/p4,它描述了 basic_istream 解析 operator>> for unsigned:

If one of these called functions throws an exception, then unless explicitly noted otherwise, the input function sets badbit in error state. If badbit is on in exceptions(), the input function rethrows the exception without completing its actions, otherwise it does not throw anything and proceeds as if the called function had returned a failure indication.

如果:

is.exceptions(std::ios::failbit | std::ios::badbit);

然后获得所需的行为。

123
456
789
Fail

更新

chico 在下面的评论中正确地指出,他希望 getline(is, s, ',') 抛出,而不是 unsigned 提取器。

查看描述此 getline 的 21.4.8.9 [string.io]/p7:

Effects: Behaves as an unformatted input function (27.7.2.3), except that it does not affect the value returned by subsequent calls to basic_istream<>::gcount(). After constructing a sentry object, if the sentry converts to true, calls str.erase() and then extracts characters from is and appends them to str as if by calling str.append(1, c) until any of the following occurs: ...

那么问题就变成了:

How does an unformatted input function behave?

27.7.2.3 [istream.unformatted]/p1 说:

Each unformatted input function begins execution by constructing an object of class sentry with the default argument noskipws (second) argument true. If the sentry object returns true, when converted to a value of type bool, the function endeavors to obtain the requested input. Otherwise, if the sentry constructor exits by throwing an exception or if the sentry object returns false, when converted to a value of type bool, the function returns without attempting to obtain any input. In either case the number of extracted characters is set to 0; unformatted input functions taking a character array of non-zero size as an argument shall also store a null character (using charT()) in the first location of the array. If an exception is thrown during input then ios::badbit is turned on315 in *this’s error state. (Exceptions thrown from basic_ios<>::clear() are not caught or rethrown.) If (exceptions()&badbit) != 0 then the exception is rethrown. It also counts the number of characters extracted. If no exception has been thrown it ends by storing the count in a member object and returning the value specified. In any event the sentry object is destroyed before leaving the unformatted input function.

315) This is done without causing an ios::failure to be thrown.

(我为便于阅读而添加的重点)

因此,这再次表明,如果此解析操作需要异常,则必须在 exceptions 中设置 badbit

关于c++ - libc++ std::istringstream 不会抛出异常。漏洞?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16468189/

相关文章:

c++11 - 为什么我不能专门化 std::tuple_element?

c++ - 在 C++ 中使用静态类

c++ - UWP - 跨 WinRT 模块重用字符串解析函数的建议方法

c++ - 游戏窗口截图

C++模板模板参数类型推导

c++ - 我如何针对在 xcode/clang/macos 中使用 libc++ 编译的静态库编译应用程序?

c++ - MacOs - 编译 c++ OpenCv 返回未找到体系结构 x86_64 的符号

c++ - 用作初始值设定项时,空括号 (“T()” ) 和空大括号 (“T{}” ) 有什么区别吗?

ruby - 是{ 'symbol name' : "some value" } valid Ruby 2 syntax for Hashes?

c++ - map.find() 如何查看输出的程序集