假设C++getline()
从某个文件中读取,该文件中有一条巨大的行超过了系统的内存容量(在超过内存容量之前没有换行符(。那么while(getline(cin, line))
循环的作用是什么?
而且,如果我需要通过抛出异常或其他什么来处理这种可能的边缘情况,我该怎么做?
如果std::getline()
最多读取std::string::max_size()
个字符,它只需停止读取并在输入流上设置failbit
标志。
不过,std::string
可能会在发生之前很久就抛出类似std::bad_alloc
的内存错误。
来自cppreference(重点是我的(:
从输入中提取字符,将它们附加到str,直到出现以下情况。。。c( str.max_size((个字符存储,在这种情况下,getline设置failbit并返回。
理论上,符合标准的实现可以使max_size()
返回比可用虚拟内存更低的值,在这种情况下,读取将停止。通常情况下,情况并非如此,内存将首先耗尽。追加下一个字符将触发失败的分配处理机制,默认情况下,该机制将抛出std::bad_alloc
。
因此,为了处理错误,您可以只使用catch(std::bad_alloc&){/*...*/}
。
假设系统的内存容量小于std::string::max_size()
的值(这可能相当于64位系统上超过800万TB(,那么getline()
函数在某个阶段,当STL实现尝试(但失败(为作为getline()
调用的第二个参数传递的std::string
对象分配额外空间时,抛出std::bad_alloc
异常。
因此,您只需要将getline
调用包含在try
块中,并将catch
包含在该异常中。
如果(不太可能?(系统的可用内存超过上述max_size()
字节,则getline
调用将设置failbit
标志,并在字符串达到该限制时返回。
1例如,在我的64位Windows系统上使用Visual Studio 19时,max_len()
返回9223372036854775807
,即8388607 TB。
在我的Ubuntu 22.04上,它设置badbit
而不抛出std::bad_alloc
,除非我将其设置为在badbit
上抛出。我怀疑它是在标准中写的,但我不确定。
以下程序:
#include <iostream>
#include <string>
int main() {
std::string s;
std::getline(std::cin, s);
std::cout << "okn";
std::cout << std::cin.eof() << std::cin.bad() << std::cin.fail() << "n";
}
当使用g++ a.cpp -o a
编译并使用tr ' ' ' ' </dev/zero | ( ulimit -v 500000; ./a )
运行时(获得无限的空间流,内存限制为~500MB(会打印以下内容:
ok
011
这里还设置了CCD_ 29;可能是因为管子坏了什么的。
使用libc++的Clang表现出相同的行为。
此外,您可以清楚地看到,这正是标准库源代码中描述的行为:捕获异常,设置badbit
,忽略异常,除非流设置为在badbit
上抛出。请参见libstdc++、libc++。