C++,std::ofstream,异常
这段代码有什么问题以及如何修复它?
int _tmain(int argc, _TCHAR* argv[])
{
std::ostream * o = &std::cout;
char text[4096];
char *file = "D://test.txt";
if ( file != NULL )
{
strcpy ( text, file );
strcat ( text, ".log" );
o = & std::ofstream ( text );
}
*o << "test"; //Exception
return 0;
}
What is wrong in this code and how to fix it?
int _tmain(int argc, _TCHAR* argv[])
{
std::ostream * o = &std::cout;
char text[4096];
char *file = "D://test.txt";
if ( file != NULL )
{
strcpy ( text, file );
strcat ( text, ".log" );
o = & std::ofstream ( text );
}
*o << "test"; //Exception
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
它不应该编译;表达式
std::ofstream( text )
是一个右值(临时的),并且 C++ 不允许您获取该地址
(运算符
&
)临时的。而临时的生命周期只是直到完整表达式结束,所以它的析构函数将被调用
(并且它驻留的内存可以用于其他事情)一旦
您在语句末尾传递
;
。仅将
ofstream
设为命名局部变量也无济于事,因为变量的生命周期仅到块的末尾
它被声明(下一个
}
)。你必须定义if
之前的std::ofstream
,打开它并在if中设置o
,例如:
It shouldn't compile; the expression
std::ofstream( text )
is anrvalue (a temporary), and C++ doesn't allow you to take the address
(operator
&
) of a temporary. And the lifetime of a temporary is onlyuntil the end of the full expression, so its destructor will be called
(and the memory it resides in may be used for other things) as soon as
you pass the
;
at the end of the statement.Just making the
ofstream
a named local variable doesn't help, either,since the lifetime of a variable is only to the end of the block in
which it was declared (the next
}
). You have to define thestd::ofstream
before theif
, and open it and seto
in the if,e.g.:
o = & std::ofstream ( text );
这会创建一个临时 ofstream 对象,其地址被分配给o
但该对象立即被销毁,因此o
指向已删除的对象。这应该有效(使用静态):o = & std::ofstream ( text );
this creates a temporary ofstream object whose address is assigned too
but the object is instantly destroyed, soo
points to a deleted object. This should work (using static):问题是这段代码会导致未定义的行为:
当您编写
This 时,会创建一个临时的 ostream 对象,其生命周期在其所在的语句完成执行后立即结束。当您获取其地址并将其分配给指针
o
时,该指针现在指向一个生命周期即将结束的临时对象。一旦该语句执行完毕,o
现在就指向一个生命周期已结束的对象,因此使用该对象具有未定义的行为。因此,当您编写时,您试图对死对象执行操作,从而导致问题。
要解决此问题,您应该
o = new std::ofstream(text);
来动态分配ofstream
,这会创建对象,使其生命周期延长到过去语句末尾,或_tmain
顶部声明std::ofstream
,以便其生命周期延伸到函数的其余部分。希望这有帮助!
The problem is that this code results in undefined behavior:
When you write
This creates a temporary
ostream
object whose lifetime ends as soon as the statement it's in finishes executing. When you take its address and assign it to the pointero
, the pointer now points at a temporary object whose lifetime is about to end. As soon as the statement finishes executing,o
is now pointing at an object whose lifetime has ended, so using that object has undefined behavior. Consequently, when you writeYou're trying to perform an operation on a dead object, causing problems.
To fix this, you should either
ofstream
by writingo = new std::ofstream(text);
, which creates the object such that its lifetime extends past the end of the statement, orstd::ofstream
at the top of_tmain
so that its lifetime extends throughout the rest of the function.Hope this helps!
这
将创建临时对象,
o
开始指向该对象的地址,稍后(在执行该行之后)该对象被销毁。因此未定义的行为(取消引用无效指针时)。解决方案 - 使用
new
创建它:但不要忘记在
return
之前释放分配的内存:This
creates temp object,
o
starts pointing to the address of this object and later(right after the execution of this row) the object is destroied. Thus undefined behavior (when dereferencing invalid pointer).The solution - create it with
new
:BUT don't forget to free the allocated memory, before
return
:我担心您正在以一种非常不健康的方式混合 C 和 C++。
首先,我衷心推荐使用
std::string
而不是char*
,相信我,你的麻烦会少得多。其次,您应该小心指针:如果您不小心,它们可能会指向内存中不再托管任何“活动”对象的位置。
我建议使用以下代码:
它说明了如何避免陷入的两个陷阱:
不幸的是,目前
std::string
和std::fstream
(及其配偶)不能很好地混合。历史缺陷...如果我没记错的话,已在 C++0x 中修复。You are mixing C and C++ in a very unhealthy way, I fear.
First, I heartily recommend using
std::string
instead of achar*
, believe me, you'll have far less troubles.Second, you should beware of pointers: they may point, if you are not careful, to places in memory that no longer host any "live" object.
I would propose the following code:
Which illustrate how to avoid the two pitfalls you fell into:
std::string
I avoid allocating a statically sized buffer, and thus I do risk a buffer overflow. Furthermore operations are so much easier.It is unfortunate that
std::string
andstd::fstream
(and consorts) do not mix so well, at the moment. Historical defect... fixed in C++0x if I remember correctly.右侧表达式创建一个临时变量,您将获得临时变量的地址,该临时变量在表达式末尾被销毁。之后使用
o
将调用未定义的行为。你应该这样做:
The right-side expression creates a temporary and you get the address of the temporary which is destroyed at the end of the expression. After that using
o
would invoked undefined behaviour.You should be doing this: