Qt3D custom mesh "Invalid address specified to RtlValidateHeap" runtime error - c++

I made a custom mesh class inherited Qt3DRender::QGeometryRenderer to draw lines in Qt3D and use it in the same way as Qt3DExtras::QShpereMesh or others. Here the source( .h , .cpp )
And on test with single line creation everithing as i expected, line creates and destroy without an error. But if do test with std::vector<Qt3DCore::QEntity*> and put to it 100 Qt3DCore::QEntity* and add them line as a component i have heap error.(here test project)
Version of Qt:6.1.0.
In Visual Studio 2019 CE with DEBUG 64bit build the runtime error message is:
HEAP[QLineMesh_test.exe]: Invalid address specified to RtlValidateHeap( 0000013BF0630000, 0000013BF522D060 ) QLineMesh_test.exe has triggered a breakpoint.
and VS points to breakpoint line in file debug_heap.cpp:
// This function is provided for backwards compatibility only. It returns TRUE
// if the given block points to an allocation from the OS heap that underlies
// this CRT debug heap. Back when the CRT used its own OS heap (prior to Dev10),
// this function would thus also tell you whether the block was allocated by this
// debug heap. Now, it just tells you whether the block was allocated by some
// debug heap.
extern "C" int __cdecl _CrtIsValidHeapPointer(void const* const block)
{
if (!block)
return FALSE;
return HeapValidate(__acrt_heap, 0, header_from_block(block)); ///<-----breakpoint here on HeapValidate
}
In VS RELEASE 64bit build breakpoint is in qarraydata.h at QArrayData::reallocateUnaligned function call.
In QtCreator with MSVC2019 64bit and minGW64-bit builds program terminated after same behaviour but without such deep explanation.
May be the error happen in function which generate the vertex data of mesh and put it to QByteArray for later usage in Qt3DCore::QBuffer.The fragment code of function from here:
inline void QLineMesh::generateVertexData()
{
...
vertex_buf.clear();
vertex_buf.resize((3 + 3) * 6 * sizeof(float));
float* possitions = reinterpret_cast<float*>(vertex_buf.data());
int index = 0;
for (auto& v : vertices)
{
possitions[index++] = v.x();
possitions[index++] = v.y();
possitions[index++] = v.z();
}
};
I can`t imagene how the heap can be affected by this mesh creation class if it's just store pointers and logic to how to manage it.
UPDATE:
In Qt 5.15.2 everithing works as expected without errors. Source in question support both versions.

Related

Debug Assertion Failed! Expression: __acrt_first_block == header

I am trying to test the dll which I wrote with GoogleTest and when I call one of the tests It throws me this error:
I have come to the conclusion that the problem is in assigning memory to vectors but I don't know how to resolve this as I am fairly new to C++ programming. The code is as follows:
#ArraysCPP11.h
#ifdef ARRAYSCP11_EXPORTS
#define ARRAYSCP11_API __declspec(dllexport)
#else
#define ARRAYSCP11_API __declspec(dllimport)
#endif
__declspec(dllexport) void removeWhiteSpaces(std::vector<std::string> v, std::vector<std::string> &output);
#ArraysCPP11.cpp
void removeWhiteSpaces(std::vector<std::string> v, std::vector<std::string> &output) { //odstranjevanje presledkov iz vector-ja (vsak drugi element je bil presledek)
for (std::vector<std::string>::iterator it = v.begin(); it != v.end(); it++) {
std::string buffer = *it;
if (isdigit(buffer[0])){;
output.push_back(*it);
}
}
}
#TestTemp.h
template<class T>
class TestTemp
{
public:
TestTemp();
void SetValue(T obj_i);
T GetValue();
bool alwaysTrue();
bool TestTemp<T>::formattingTest(std::string input, std::vector<std::string> realVector, std::vector<std::string> formattedInput);
private:
T m_Obj;
};
template<class T>
inline bool TestTemp<T>::formattingTest(std::string input, std::vector<std::string> realVector, std::vector<std::string> formattedVector) {
std::string input2 = input;
// std::vector<std::string> fResult;
std::string first;
std::string second;
bool endResult = true;
std::vector<std::string> end;
//std::vector<std::string> result = split(input2, ' ');
removeWhiteSpaces(formattedVector,end);
std::vector<std::string>::iterator yt = realVector.begin();
for (std::vector<std::string>::iterator it = end.begin(); it != end.end(); it++, yt++) {
first = *it;
second = *yt;
if (first.compare(second) != 0) {
endResult = false;
break;
}
}
return endResult;
}
#ArraysCPP11-UnitTest.cpp
struct formattingTesting{
// formattingTesting* test;
std::string start;
std::vector<std::string> endResult;
formattingTesting() {
}
explicit formattingTesting(const std::string start, const std::vector<std::string> endResult)
: start{start}, endResult{endResult}
{
}
};
struct fTest : testing::Test {
formattingTesting* test;
fTest() {
test = new formattingTesting;
}
~fTest() {
delete test;
}
};
struct format {
std::string start;
std::vector<std::string> end;
};
struct formTest : fTest, testing::WithParamInterface<format> {
formTest() {
test->start = GetParam().start;
test->endResult = GetParam().end;
}
};
TEST_P(formTest, test1) {
bool endResult = true;
TestTemp<int> TempObj;
std::string first;
std::string second;
//std::string start ("1 2 3 4 5 6 7 8 9 10");
//std::vector<std::string> end = { "1","2","3","4","5","6","7","8","9","10" };
std::vector<std::string> start2 = { "1","","2","3","4","5","6","7","8","9","10" };
std::string start = GetParam().start;
std::vector<std::string> end = GetParam().end;
bool result = TempObj.formattingTest(start,end,start2);
EXPECT_TRUE(result);
}
INSTANTIATE_TEST_CASE_P(Default, formTest, testing::Values(
format{ "1", {"1"} },
format{ " ", {} },
format{ "1 2 3 4 5",{"1","2","3","4","5"} },
format{ "1 2 3 4 5 6", {"1","2","3","4","5","6"} }
));
int main(int argc, char** argv)
{
testing::InitGoogleTest(&argc, argv);
RUN_ALL_TESTS();
return 0;
}
As this is a DLL, the problem might lie in different heaps used for allocation and deallocation (try to build the library statically and check if that will work).
The problem is, that DLLs and templates do not agree together very well. In general, depending on the linkage of the MSVC runtime, it might be problem if the memory is allocated in the executable and deallocated in the DLL and vice versa (because they might have different heaps). And that can happen with templates very easily, for example: you push_back() to the vector inside the removeWhiteSpaces() in the DLL, so the vector memory is allocated inside the DLL. Then you use the output vector in the executable and once it gets out of scope, it is deallocated, but inside the executable whose heap doesn't know anything about the heap it has been allocated from. Bang, you're dead.
This can be worked-around if both DLL and the executable use the same heap. To ensure this, both the DLL and the executable must use the dynamic MSVC runtime - so make sure, that both link to the runtime dynamically, not statically. In particular, the exe should be compiled and linked with /MD[d] and the library with /LD[d] or /MD[d] as well, neither one with /MT[d]. Note that afterwards the computer which will be running the app will need the MSVC runtime library to run (for example, by installing "Visual C++ Redistributable" for the particular MSVC version).
You could get that work even with /MT, but that is more difficult - you would need to provide some interface which will allow the objects allocated in the DLL to be deallocated there as well. For example something like:
__declspec(dllexport) void deallocVector(std::vector<std::string> &x);
void deallocVector(std::vector<std::string> &x) {
std::vector<std::string> tmp;
v.swap(tmp);
}
(however this does not work very well in all cases, as this needs to be called explicitly so it will not be called e.g. in case of exception - to solve this properly, you would need to provide some interface from the DLL, which will cover the vector under the hood and will take care about the proper RAII)
EDIT: the final solution was actually was to have all of the projects (the exe, dll and the entire googleTest project) built in Multi-threaded Debug DLL (/MDd)
(the GoogleTest projects are built in Multi-threaded debug(/MTd) by default)
I had a similar problem and it turned out that my unittest project was set to a different code generation runtime library - so by setting it to the same as the DLL project, then no heap exception
That verification was implemented by Microsoft software developers a long time ago in 1992 - 1993 and it is No Longer valid since in case of Heterogeneous or MPI programming a new memory Could Be allocated Not from a Local Heap.
When an application gets a memory using OpenCL or CUDA APIs a GPU driver does all memory allocations and, of course, it doesn't use the Local Heap of the application. However, the application should release the memory before it exits. At that time Microsoft's Memory Leaks Detection API detects it and that assert is displayed.
Please take a look at a Video Technical Report regarding origins of that verification:
Origins of MS Visual Studio 2015 Assert __acrt_first_block == header ( VTR-010 )
https://www.youtube.com/watch?v=NJeA_YkLzxc
Note: A weblink to the youtube video updated since I've uploaded a video with some corrections.
I encountered the same error and I found a way to get more information about the cause of the problem: It is possible to set with visual studio a breakpoint condition on the line that raise this error (so that the debugger breaks before the error message).
It is necessary to open the corresponding file (debug_heap.cpp,somewhere in "C:\Program Files (x86)\Windows Kits\10\Source") and to write the following condition:
Then we can continue debugging and when the breakpoint is hit, we can observe the address of the block that raise the error (the "block" argument of the "free_dbg_nolock" function that contains the breakpoint).
From there you can observe the memory content of the block by copying the address into the memory window (Debug->Windows->Memory). If you are lucky it may be a string or an easily recognizable variable.
You can then identify the variable that causes the bug and try to fix it.
In my case it was a variable that was created in one dll and deleted in another. To correct it I replaced all my objects by pointers to these objects in one dll.
I had the same issue with Microsoft visual studio 2019, simply fixed by changing the "Runtime library" to " Multi-Threaded Debug DLL (/MDd)"
right click on solution on "Solution Explorer" -> "properties" -> "C/C++" -> "Code Generation" , and change "Runtime library" to " Multi-Threaded Debug DLL (/MDd)"
I was seeing this error too and in my case I had all the memory model settings lined up correctly. However having recently upgraded the projects from vs2013 to vs2015 I had stale references between the .exe and .dll, so in fact I was using the old DLL built with 2013. I had to remove the reference between the .exe and .dll and re-add it to update the name of the .lib that the exe was linking against. (Right click on the "References" child item of the .exe project and "Add", while confusingly also allows you to remove a reference).

Errors with initialization of an unordered_map inside of a class

The error I'm getting is Exception thrown at 0x00007FF77339C476 in VirusSimulator.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.
I've gone through my code with Visual Studio's debugger, and it seems like the error is from an attempt to call .size() on a unordered map of class objects.
Specifically, in the implementation of "list":
size_type size() const _NOEXCEPT
{ // return length of sequence
return (this->_Mysize());
}
When stepping through with the debugger and keeping an eye on local variables, I see: this 0xccccccccccccce0c folders={ size=??? }
(folders being the map of class variables)
Just below is a section of int main() where I manually initialize a default folder in each computer's drive's map of folders:
vector<Computer> macs;
for (int i = 0; i < mac_amount; i++)
{
macs.push_back(Computer(OSX)); //Initialize a computer with an operating system
}
for (int i = 0; i < macs.size(); i++)
{
//... Here is some code initializing connections between the computer objects
//and here is the manual insert of folders into the map
macs[i].getDrive()->addFolder("default"); //This used to be in the computers constructor but I moved it out here for testing
}
definition of addFolder:
void Harddrive::addFolder(string name)
{
Folder new_folder;
new_folder.set_name(name);
folders.insert(std::pair<string, Folder>(name, new_folder));
}
Basically, a random computer object then runs a virus that attempts to install itself to every other connected computer object by accessing the list of connections that is has, which contain pointers to the other computer objects.
It then de-references these and attempts to find the default folder on each respective computer's harddrive, but then fails to do so, claiming that the folder is uninitialized?
If any other pieces of my code are needed, then the full code can be found at https://github.com/BananaSky/VirusSimulator/tree/UnstableNetworkAdditions
Most of the code I've already tested for bugs, and that's why I've only posted such a small portion.
Any help is much appreciated!! (But also, it's getting late here and I might be going to sleep soon, so I apologize if I can't respond right away)
--ALSO: Please note that this is just a simulation and that I'm not actually intending to create any form of computer virus.
Here is the section of code where the error occurs (inside Virus.cpp):
vector<int> vulnerableConnectionIPs = installedOn->getNetworkAdapter()->getConnection()->getConnections();
for (int i = 0; i < vulnerableConnectionIPs.size(); i++)
{
Computer* accessRequest = installedOn->getNetworkAdapter()->getConnection()->getConnect(vulnerableConnectionIPs[i])->giveAccess();
if (accessRequest != NULL && accessRequest != installedOn)
{
if (accessRequest->getDrive()->getFolders()) //Error occurs here
{
accessRequest->Install(this, "default"); //Infect if infectable :)
}
else
{
cout << "No folders exist on " << accessRequest->getDrive()->getModel() << endl;
}
}
}
I'm working on replicating this on a smaller scale, and I'll probably get that posted by tomorrow
A memory address of 0xcccccccccccccccc (64-bit) or 0xcccccccc (32-bit) is Visual Studio's way of denoting an uninitialized block of memory. There's also 0xfeeefeee for already free'd and 0x00000000 for a null pointer.
Check that you have actually stored a value in the variable you are trying to access.
The values actually shown from error dialogs may be offset to values close to the above locations, you'll just have to trace through the program.
Your initial description of the error also points to at least trying to de-reference a null pointer.
More code would be helpful.

" malloc error pointer being freed was not allocated " error only in simulator:

When I debug on actual devices, there is no error, but when I use the simulator, Xcode's debugger console displays the following error when running:
malloc: *** error for object 0xaaaaaaaa: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
The error always happens at the same line, which is in the constructor of another class:
Segment *segment = new Segment(0.0,0.0,3.0,1.3,10);
this->segments.push_back(segment); // Malloc error at this line
My Segment class:
class Segment {
private:
float ajc;
float frl;
std::unordered_map<int,int> jgrc;
std::vector<int> lorb;
public:
std::tuple<float,float> getMjt();
float getBuw();
….
Segment(float a, float f,float g, float lo, float u){
……
};
};
On the simulator, regardless of iOS version, the error appears. On devices, regardless of version, there is no error.
I have heard about the rule of 3, but in this case I don't think I need to apply it because the default compiler supplied code should work (unless I'm mistaken). What am I doing wrong, and how can I fix this ? Since there is no error reported on devices, should i ignore it ?
First put a NULL check to avoid the run time error. I tried a pseudo code on VS and it seemed to work. I hope your vector is similar.
Segment *segment = new Segment(0.0, 0.0, 3.0, 1.3, 10);
std::vector<Segment*> vec;
if (NULL != segment)
vec.push_back(segment);
I think there is some problem with your simulator not working fine.
The solution works, but I don't understand why. If someone with more c++ can explain it well, I will mark that as the correct answer.
The following code runs in the constructor of my class that creates the segments:
Segment *segment = new Segment(0.0,0.0,3.0,1.3,10);
this->segments.push_back(segment); // Malloc error at this line
First, I used objects instead of the pointer. Then I moved the code out of the constructor, and instead call it immediately after creating an instance of the class.
Say my class is:
class MyClass{
std::vector<Segment> segments;
}
I do :
MyClass *foo = new MyClass();
foo->createSegments();
Where:
createSegments(){
Segment segment = Segment(0.0,0.0,3.0,1.3,10);
segments.push_back(segment);
}
I'm not very experienced with C++, so I don't know why this works.I also still don't know why the original error only appeared in the simulator.

c++ program debugged well with Cygwin4 (under Netbeans 7.2) but not with MinGW (under QtCreator 4.8.1)

I have a c++ program that takes a map text file and outputs it to a graph data structure I have made. I am using QT as I needed cross-platform program and GUI as well as visual representation of the map. I have several maps in different sizes (8x8 to 4096x4096).
I am using unordered_map with a vector as key and vertex as value, I'm sending hash(1) and equal functions which I wrote to the unordered_map in creation.
Under QT I am debugging my program with QT 4.8.1 for desktop MinGW (QT SDK), the program works and debugs well until I try the largest map of 4096x4096, then the program gets stuck with the following error:
the inferior stopped because it received a signal from operating system
When debugging, the program halts at the hash function which used inside the unordered_map and not as part of the insertion state, but at a getter(2).
Under Netbeans IDE 7.2 and Cygwin4 all works fine (debug and run).
Some code info:
typedef std::vector<double> coordinate;
`typedef std::unordered_map<coordinate const*, Vertex<Element>*, container_hash, container_equal> vertexsContainer;`
`vertexsContainer *m_vertexes`
(1) hash function:
struct container_hash
{
size_t operator()(coordinate const *cord) const
{
size_t sum = 0;
std::ostringstream ss;
for ( auto it = cord->begin() ; it != cord->end() ; ++it )
{
ss << *it;
}
sum = std::hash<std::string>()(ss.str());
return sum;
}
};
(2) the getter:
template <class Element>
Vertex<Element> *Graph<Element>::getVertex(const coordinate &cord)
{
try
{
Vertex<Element> *v = m_vertexes->at(&cord);
return v;
}
catch (std::exception& e)
{
return NULL;
}
}
I was thinking maybe it was some memory issue at the beginning, so before I was thinking of trying Netbeans I checked it with QT on my friend pc with a 16GB RAM and got the same error.
Update:
I try to run this on visual studio 2012, I got a bad_alloc error which halt my program, when looking at task manager I saw the memory assigned to the program was going up to 2GB, could be it's because it's a 32bit program?
Update
I debugged my program under Netbeans with 32bit architecture and Cygwin4 and all worked fine, so maybe it is not a 32 bit problem, also the memory used with netbeans was 1.5GB, so how in MinGW and VS2012 it's going up to 2GB?

_DebugHeapDelete Access Violation at termination

I'm getting a weird access violation at the end of my main whose cause I'm having some difficulties finding.
When shutting down my application I get an access violation in the following:
xdebug
// TEMPLATE FUNCTION _DebugHeapDelete
template<class _Ty>
void __CLRCALL_OR_CDECL _DebugHeapDelete(_Ty *_Ptr)
{ // delete from the debug CRT heap even if operator delete exists
if (_Ptr != 0)
{ // worth deleting
_Ptr->~_Ty();
// delete as _NORMAL_BLOCK, not _CRT_BLOCK, since we might have
// facets allocated by normal new.
free(_Ptr); // **ACCESS VIOLATION**
}
}
Stack trace:
> msvcp100d.dll!std::_DebugHeapDelete<void>(void * _Ptr) Line 62 + 0xa bytes C++
msvcp100d.dll!std::numpunct<char>::_Tidy() Line 190 + 0xc bytes C++
msvcp100d.dll!std::numpunct<char>::~numpunct<char>() Line 122 C++
msvcp100d.dll!std::numpunct<char>::`scalar deleting destructor'() + 0x11 bytes C++
msvcp100d.dll!std::_DebugHeapDelete<std::locale::facet>(std::locale::facet * _Ptr) Line 62 C++
msvcp100d.dll!std::_Fac_node::~_Fac_node() Line 23 + 0x11 bytes C++
msvcp100d.dll!std::_Fac_node::`scalar deleting destructor'() + 0x11 bytes C++
msvcp100d.dll!std::_DebugHeapDelete<std::_Fac_node>(std::_Fac_node * _Ptr) Line 62 C++
msvcp100d.dll!_Fac_tidy() Line 41 + 0x9 bytes C++
msvcp100d.dll!std::_Fac_tidy_reg_t::~_Fac_tidy_reg_t() Line 48 + 0xe bytes C++
msvcp100d.dll!std::`dynamic atexit destructor for '_Fac_tidy_reg''() + 0xf bytes C++
msvcp100d.dll!_CRT_INIT(void * hDllHandle, unsigned long dwReason, void * lpreserved) Line 415 C
msvcp100d.dll!__DllMainCRTStartup(void * hDllHandle, unsigned long dwReason, void * lpreserved) Line 526 + 0x11 bytes C
msvcp100d.dll!_DllMainCRTStartup(void * hDllHandle, unsigned long dwReason, void * lpreserved) Line 476 + 0x11 bytes C
Anyone got any ideas as to what might cause this?
I read something about facets being cached not sure if thats related?
If you override the operator new and use you may meet the same cause as me.
the code may be like
#include "yournew" //override new declare ..
#include "fstream"
std::fstream f
f.open(...)
because the iostream is template so the new of _Fac_node use your operator new. but when exit, your memory pool may exit before _Fac_tidy, then when ~_Fac_tidy() run,the program crashed.
Memory corruption bugs can (obviously) cause this (and many other kinds) of failure.
Have you tried using valgrind (memcheck) or Rational Purify against this? It will probably report the problem (possibly buried in a whole lot of other information if this would be the first time you ran such a check on your code base. You will still want to devise a minimal 'main' implementation that exhibits the behaviour to run under a memory and bounds checker
$0.02
PS. just in case, memory corruption bugs usually arise
by dereferencing stale pointers (after free/delete)
by writing beyond the end of an allocated buffer
by freeing/deleting previously pointers (mostly a symptom of bad ownership tracking)
The first, accepted, response is correct, but it does not show exactly the reason and hence the way of fixing it. According to the listed part of the call stack, I've encountered into the same problem with VC++8 (MS VS 2005) but in the different case: my CLR DLL caused AV at the same point of the code.
From the listed call stack it is seen that the code of <xdebug> that is normally compiled into msvc*.dll is called but at that moment the _Ptr already has wrong value. Hence, there is some code that either already freed the object under this pointer or set an exit hook to free the uninitialized object.
If _STATIC_CPPLIB was defined, the <xdebug> code could be complied into other modules that are loaded into the application process. Then, one exit procedure of those modules could be called prior to another one in msvcp100d.dll and thus could normally free the facet object. In my case, with _STATIC_CPPLIB defined, both the modules (exe and clr dll) were compiled.
Solution for VC++8,9
Check the final compiler options in the "Command Line" section for the presence /D "_STATIC_CPPLIB". Undefining _STATIC_CPPLIB and recompiling affected modules fixes the AV at program termination.
Note on _STATIC_CPPLIB
For VC++9 _STATIC_CPPLIB, at MSDN, there is the note that
the combination of the _STATIC_CPPLIB preprocessor definition and the
/clr or /clr:pure compiler option is not supported.
And there are no mentions on _STATIC_CPPLIB for higher VS versions.
For higher VS versions and VS 10 in particular, I suppose that the code dependent on _STATIC_CPPLIB still exists. In the TS's case, if _STATIC_CPPLIB is still used in the compiler options of any TU that includes <string> or other headers including <locale>, this improper combination could lead to AV.
I believe you're experiencing the same bug I did in the MSVC10 runtime. To my understanding, it is caused by the runtime deleting a global facet when a DLL unloads, and then deleting it again when the process ends. If you link everything statically, it shouldn't happen. It also won't happen in MSVC9, either with static or shared linkage.
TLDR; used a custom Allocation class in my code which tracks all memory crated and deleted using new. Since the shutdown function for this class is called before Microsoft's CRT clean up and frees any memory created by this. I simply overrode the CRT code in locale0.cpp in my code, and commented out the loop to free CRT memory. As it's already deleted by my class.
The application is attempting to delete memory it created for wostreambuf* and ostreambuf*., in my instance as part of a lambda function.
It created the memory which got stored in __PURE_APPDOMAIN_GLOBAL static _Fac_node* _Fac_head = nullptr; to be deleted after execution of the program ends. By calling the destructor ~_Fac_tidy_reg_t() from _Fac_tidy_reg_t.
Since in my application i override the new and delete functions and manage the memory myself. The program at the end of execution automatically deletes any memory it used, so when the CRT calls this ~_Fac_tidy_reg_t() destructor the memory is already freed, however not necessarily "nullptrjust marked as unsed. When~_Fac_tidy_reg_t()attempts to cycle through the_Fac_head` the memory is already freed and therefore causes a exception.
To solve this i simply overload ~_Fac_tidy_reg_t() and commented out the code to run the loop to delete the already deleted memory address's.
#if defined(PLATFORM_WINDOWS)
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// class locale basic member functions
#include <crtdbg.h>
//#include <internal_shared.h>
#include <xfacet>
// This must be as small as possible, because its contents are
// injected into the msvcprt.lib and msvcprtd.lib import libraries.
// Do not include or define anything else here.
// In particular, basic_string must not be included here.
// This should probably go to a compiler section just after the locks - unfortunately we have per-appdomain
// and per-process variables to initialize
//#pragma warning(disable : 4073)
//#pragma init_seg(lib)
_STD_BEGIN
[[noreturn]] _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL _Xbad_alloc();
struct _Fac_node { // node for lazy facet recording
_Fac_node(_Fac_node* _Nextarg, _Facet_base* _Facptrarg)
: _Next(_Nextarg), _Facptr(_Facptrarg) {} // construct a node with value
~_Fac_node() noexcept { // destroy a facet
delete _Facptr->_Decref();
}
#ifdef _DEBUG
void* operator new(size_t _Size) { // replace operator new
void* _Ptr = _malloc_dbg(_Size > 0 ? _Size : 1, _CRT_BLOCK, __FILE__, __LINE__);
if (!_Ptr) {
_Xbad_alloc();
}
return _Ptr;
}
void operator delete(void* _Ptr) noexcept { // replace operator delete
_free_dbg(_Ptr, _CRT_BLOCK);
}
#endif // _DEBUG
_Fac_node* _Next;
_Facet_base* _Facptr;
};
__PURE_APPDOMAIN_GLOBAL static _Fac_node* _Fac_head = nullptr;
* WHILE LOOPS IS COMMENTED OUT */
struct _Fac_tidy_reg_t {
~_Fac_tidy_reg_t() noexcept { // destroy lazy facets
//while (_Fac_head != nullptr) { // destroy a lazy facet node
// _Fac_node* nodeptr = _Fac_head;
// _Fac_head = nodeptr->_Next;
// delete nodeptr;
//}
}
};
__PURE_APPDOMAIN_GLOBAL const _Fac_tidy_reg_t _Fac_tidy_reg;
#if defined(_M_CEE)
void __CLRCALL_OR_CDECL _Facet_Register_m(_Facet_base* _This)
#else // defined(_M_CEE)
void __CLRCALL_OR_CDECL _Facet_Register(_Facet_base* _This)
#endif // defined(_M_CEE)
{ // queue up lazy facet for destruction
_Fac_head = new _Fac_node(_Fac_head, _This);
}
_STD_END
#endif // PLATFORM_WINDOWS