从流提取到 char 数组或 std::string 的最安全方法
我担心缓冲区溢出,并且需要从派生自 std::istream 的类中获取一些字符。据我了解,如果没有我自己的>>,就无法直接从 istream 流式传输到 std::string。操作员。所以我正在考虑将内容流式传输到 char 数组,然后将其放入 std::string 中。下面是一个简单的例子:
char CharArray[1000] = {0};
SomeIStream >> CharArray;
std::string StuffFromStream(CharArray);
但是,似乎没有办法知道 CharArray 不会溢出。流提取运算符是否有写入 chararray 的最大值?有什么方法可以检查抢先提取的金额吗?难道这都是错的吗?有比这更好的方法吗?
Edit1:,我修复了我的不是内存泄漏。无需调用删除。我不敢相信我竟然这么做了。
Edit2:使用>>的建议建议直接到字符串。我在代码库中尝试了这个问题的来源,但失败了。说找不到适合操作员的匹配项。然后我尝试使用 std::fstream ,但它再次失败。在简单的简约项目中尝试 std::fstream 代码成功了。这告诉我,我的大型项目还存在其他问题。这个问题的初衷已经不成立了。
编辑3:我解决了这个问题。我试图流式传输到 typedef String,我认为它实际上是 std::string,但它实际上是 const std::String。当然,没有用于写入不可写对象的流提取运算符,因此它只是为我提供了 istream 标头中列出的所有运算符(我需要的运算符位于字符串标头中)。
感谢那些指出我错误的研究并为我指明正确方向的人。
I am concerned about buffer overflows, and I need to get some characters out of a class that derives from std::istream. From what I understand there is no way to stream to an std::string directly from an istream, without my own >> operator. So I was considering streaming the contents to a char array, then putting that into a std::string. Here is a simple example:
char CharArray[1000] = {0};
SomeIStream >> CharArray;
std::string StuffFromStream(CharArray);
However, there seems to be no way to know that CharArray will not be overflowed. Is there some maximum the stream extraction operator will write to chararray? Is there some way to check how much will be extracted preemptively? Is this just all wrong, Is there some way that is much better than this?
Edit1:, I fixed my not a memory leak. No need to call delete. I can't believe I did that.
Edit2: The suggestion to use the >> directly to string was suggested. I attempted that previous in the code base this problem came from and it failed. Saying that no suitable match for the operator could be found. I then tried with an std::fstream and it failed again. Trying the std::fstream code in simple minimalistic project succeeded. This tells me that something else is wrong with my larger project. The original intent of this question is no longer valid.
Edit3: I solved this. I was attempted to stream to a typedef String, which I thought was actually and std::string, but it was really a const std::String. Naturally there isn't a stream extraction operator for writing to an unwritable object, so it just gave me all the operators listed in the istream header (the one I needed was in the string header).
Thanks to the people who pointed out my faulty research and pointe me in the right direction.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
如果您(正确地)从 std::istream 继承,那么您不需要做任何特殊的事情,只需使用
operator >> (std::istream&、std::string&)
。当我说“正确”时,我的意思是重写 istream 中适当的虚拟函数。
“我知道如果在删除之前出现异常,就会泄漏内存。”不,不会。您没有使用
new
分配CharArray
;对其调用delete
不会执行您想要的操作。If you've (properly) inherited from std::istream, then you don't need to do anything special and can just use
operator >> (std::istream&, std::string&)
.When I say "properly," I mean overridden the appropriate virtual functions from istream.
"I know that if there is an exception before the delete this will leak memory." No it won't. You didn't allocate
CharArray
withnew
; callingdelete
on it will not do what you want.将老式 C 风格的字符数组与流混合在一起?看起来像是一些非常混乱的代码。
抛开注释不谈,直接提取到字符串即可。您可以将其(通过
c_str()
方法)传递给需要const char*
参数的 C 风格 API。如果由于某种奇怪的原因您确实需要一个 char 数组,则可以在检查边界后将复制
从string
安全地复制到 char 数组。顺便说一句,您已经非常清楚地说明了 的主要方式魔法数字是邪恶的。就您而言,所讨论的幻数是
1000
。您不知道1000
是否合适——不太大,也不太小——无需完全猜测。在编程中,猜测经常==崩溃。或者更糟糕的是,没有崩溃。顺便说一句,您正在
删除
上面的自动变量。你不这样做。当且仅当您使用new
时才使用delete
。您没有新建
,所以不要删除
。顺便说一句,如果你只想将整个流提取到一个字符串中,你可以这样做:
Mixing old-school C-style char arrays with streams? Seems like some very confused code.
Commentary aside, just extract directly to a string. You can pass that (via the
c_str()
method) to C-style APIs that expectconst char*
parameters. And if for some bizarre reason you really do nead a char array, you cancopy
from thestring
to the char array safely, after checking bounds.By the way, you've pretty clearly illustrated the main way in which magic numbers are evil. In your case, the magic number in question is
1000
. You have no idea that1000
is appropriate -- not too big, not too small -- without totally guessing. In programming, guessing often == crashing. Or even worse, not crashing.By the way 2, you are
delete
ing an automatic variable above. You don't do this. Usedelete
if and only if you usenew
. You didn'tnew
, so don'tdelete
.By the way 3, if you just want to extract the whole stream in to a string, you can just do this:
如果你想将整个流读入一个字符串,这不是非常有效,但很安全:(
注意额外的括号,以避免最麻烦的解析)
如果你想读取最多“n”个字符:
注意这不会以空值终止数组。如果您想让数组的最后一个字符保持不变,请传递
sizeof(char_array) - 1
。If you want to read the whole stream into a string, this is not terribly efficient, but is safe:
(note the extra parenthesis, to avoid the most-vexing-parse)
If you want to read up to "n" characters:
note that this won't null-terminate the array. Pass
sizeof(char_array) - 1
instead if you want to leave the array's last char untouched.所有流都提供 .str() 方法,该方法将提供其缓冲区的副本作为 std::string (或 wstring 或其他 typedef 的任何内容)。
另外,你在堆栈上声明了一个数组,然后试图删除它,这就是UB。
All streams offer the .str() method, which will provide a copy of their buffer as a std::string (or wstring or whatever for other typedefs).
Also, you declared an array on the stack and then tried to delete it, which is UB.
这就是我通常采用的方法(来自 Bruce Eckel 的“Thinking in C++”)::
在上面的代码中,整个文件被视为一个字符流,然后放入一个字符串中。这仅作为示例示出。
This is what my approach usually is (from "Thinking in C++" by Bruce Eckel)::
In the above code the whole file is taken as a character stream and then put into a string. This is shown just as an example.