我遇到了一个有趣的问题,它似乎是visual studio 2013的结果,当它们被调用删除操作符时,实际上并未删除fstreams。下面的代码是一个简单的程序,在Visual Studio 2013中使用默认的调试模式进行编译时,其性能与预期完全相同。当代码以释放模式编译时(生成调试信息打开以便可以完成一些调试),删除操作符行为将取决于删除操作符的内容。如果delete操作符包含一个cout,它会立即调用分配的内存部分,如果它没有包含一个cout,那么它将一直运行crtexe.c中的exit函数,直到它被调用称为foo互斥处于某种无效状态,导致“访问冲突读取位置0xFEEEFEF6”。在发布模式下调用删除时,fstreams不会被删除
#include <cstdlib>
#include <fstream>
#include <mutex>
#include <iostream>
using namespace std;
mutex foo;
void* operator new(unsigned int size)
{
lock_guard<mutex> memoryLock(foo);
void* alloc = malloc(size);
cout << "Allocating " << size << " bytes for " << alloc << endl;
return alloc;
}
void* operator new[](unsigned int size)
{
lock_guard<mutex> memoryLock(foo);
void* alloc = malloc(size);
cout << "Allocating " << size << " bytes for " << alloc << endl;
return alloc;
}
void operator delete(void* ptr)
{
lock_guard<mutex> memoryLock(foo);
cout << "Deallocating " << ptr << endl;
free(ptr);
}
void operator delete[](void* ptr)
{
lock_guard<mutex> memoryLock(foo);
cout << "Deallocating " << ptr << endl;
free(ptr);
}
int main()
{
cout << "Address of Mutex: " << &foo << endl;
cout << "Creating fstream... " << endl;
fstream *blarg = new fstream("blarg.txt", ios::out);
cout << "Deleteing fstream..." << endl;
delete blarg;
cout << "fstream deleted..." << endl;
cout << "Exiting main..." << endl;
return 0;
}
此程序输出:
Address of Mutex: 00DD6658
Creating fstream...
Allocating 192 bytes for 003ABB00
Allocating 8 bytes for 00392A40
Deleteing fstream...
Deallocating 003ABB00
fstream deleted...
Exiting main...
,然后崩溃与访问冲突。
如果您在删除操作符中设置了断点,您将看到对其的调用与输出所示完全相同。如果你离开了这些断点,但注释掉了cout行,那么调试过的命令从不碰到delete操作符,直到它到达crtexe.c中的退出函数。
最大的问题是,由于某种原因,fstream(或者至少并非全部资源)在看起来像其他全局资源已经被销毁之后被删除,这意味着fstream的动态分配的内存对象正在调用自定义它使用的资源无效后删除运算符。
我应该能够为我的应用程序产生一种解决方法,这点真的不是我关心的问题,我只是想了解发生了什么的'为什么'。为什么fstream的析构函数和/或释放它的内存会被延迟?如果有的话,可以做什么来防止这种行为?我能期待其他类可能产生这种行为吗?
了解发生事件的顺序将是有用的。互斥类可能在其构造函数/析构函数中调用New和Delete?这会在这里造成问题。我会在每一行main和new和delete操作符前放置一些COUT。 – user3344003 2014-10-29 03:48:50
发现了一些有趣的效果与couts喷洒程序。老实说,这很奇怪。用新信息编辑问题。 – Darinth 2014-10-29 04:11:35
这些信息至少让我了解如何删除一个对象而不删除它的所有资源。无论是什么8字节的分配,fstream可能都会以某种方式排队,以便在应用程序退出时被删除。我仍然试图围绕为什么在删除cout时调试器不会命中删除操作符。操作员实际上是不是在运行,还是调试器没有机会看到它? – Darinth 2014-10-29 04:25:03