I have MessagesViewer frame that I want to control the uniqueness of,
with this piece of code:
MessagesViewer* m_pMsgViewer = NULL;
void Application::ShowMessagesViewer()
{
if (m_pMsgViewer == NULL)
{
m_pMsgViewer = new MessagesViewer(
wxGetApp().GetContainer()->GetAppData()->GetMessages()
);
}
else
{
m_pMsgViewer->FillPage(wxGetApp().GetContainer()->GetAppData()->GetMessages());
m_pMsgViewer->SetFocus();
}
}
But when I call this for the first time, m_pMsgViewer starts to refer to valid data in the memory. When I close MessagesViewer frame, it destroys it automatically, but the pointer is still referencing to old address, and I can't control destroying the frame from this client code.
How can I dereference a pointer to destroyed frame?
#bogdan already proposed a good solution, but there is another, even more automatic one: store your frame pointer in wxWeakRef<> instead. I.e. keep exactly the same code as now but replace the declaration with
wxWeakRef<MessagesViewer> m_pMsgViewer;
The weak reference will be automagically reset to NULL when the window is destroyed.
One solution is to set m_pMsgViewer back to nullptr when MessagesViewer is closed. A safe way to do that is to add a handler for wxEVT_CLOSE_WINDOW to your frame. For example, add the following code to MessagesViewer's constructor:
Bind(wxEVT_CLOSE_WINDOW, [](wxCloseEvent& evt)
{
m_pMsgViewer = nullptr;
evt.Skip();
});
evt.Skip() lets the event propagate further to the default handler provided by wx.
This simple example assumes that m_pMsgViewer is a global variable. If it's actually contained within the Application object, you'll have to add some way to access it.
The obvious alternative of adding such code to MessagesViewer's destructor is not a very good idea, as the actual destruction of the MessagesViewer object is delayed according to the docs, so it would be theoretically possible for Application::ShowMessagesViewer() to call FillPage() on a frame that has been closed and marked for destruction but not actually destroyed yet.
Handling the close event resets the pointer early on, thus avoiding the problem above.
You need to mark somehow that MessagesViwer has been destroyed and cannot be referenced any more. This means some extra info in addition to m_pMsgViewer.
Related
I have a Layer class which contains certain objects like buttons, sliders etc. I've built the Layer class so that it's capable of refreshing itself. Essentially, it deletes all/most of its objects and then recreates them. The reason for that is that I have various functionalities like changing font size or the theme of my UI and I want to have the changes be apparent immediately.
The only way to accomplish this consistently is to simply rebuild everything, because the themes and font sizes affect both the look and the layout of everything. This all works really well and I'm satisfied with the system.
However, issues (and by issues I mean crashes) arise when one the objects that belongs to the layer initiates the refreshing. For instance, I have a font size slider which is supposed to change the font size and then make the layer refresh. It has a callback to the refresh function of the layer, captured by a lambda, and stored in a member std::function object. What happens when the function is executed is that at some point, before the calling function is finished, the slider, of course, gets destroyed and destroys the function along with it. Thus the function that's currently running stops existing and the program crashes.
My question is what would be a good and elegant way of accomplishing this behavior that doesn't result in crashes via this paradoxical situation?
EDIT: Code
class MySlider : public MyNode
{
//... various other class members
std::function<void()> functionOnRelease = nullptr;
MySlider::MySlider(/*constructor arguments*/)
{
this->preferenceKey = key;
slider->addTouchEventListener([=](Ref* sender, ui::Widget::TouchEventType type)
{
if (type == ui::Widget::TouchEventType::ENDED)
on_release();
});
//... remainder of constructor body
}
void MySlider::set_function_on_release(const std::function<void()>& functionOnRelease)
{
this->functionOnRelease = functionOnRelease;
}
void on_release()
{
if (preferenceKey.empty() == false)
PREFM->set_preference(preferenceKey, slider->getPercent() + min);
if (functionOnRelease)
functionOnRelease();
//the program crashes at this point when the slider gets destroyed
}
}
//The layer in question and the function that creates its slider
void Options::create_font_size_slider()
{
NodeVector sliders;
//there's a static create function convention imposed by the engine
auto fontSizeSlider = MySlider::createWithPreferenceAutomatic("Font Size: ", "FontSizePercentage", 50, 150, false, sliders);
fontSizeSlider->set_function_on_release([=] { this->refresh(); /*this kills the slider*/});
}
EDIT 2:
I've managed to avert the crash by a simple and ugly hack. I've forced the refresh() function to happen on a separate thread after a slight delay (0.05 seconds). This gives enough time for everything to happen without the delay being noticeable. I can live with the potential occasional crash in the event of a really slow device and strange thread scheduling since everything that needs to be done gets done before the crash can occur.
You could tackle this by reference counting your objects (as COM does, for example). Basically:
Retain () bumps the reference count of an object.
Release () decrements the reference count of an object, and, if it is now zero, deletes it.
An object starts life with a reference count of 1 and you never explicitly delete a reference counted object (protect the destructor).
Now, when an object wants to trigger a refresh, it can call Retain on itself first. When control returns to the object, it can call Release and then immediately return. The call to Release might delete the object, but that doesn't matter so long as it doesn't touch its instance data subsequently.
Reference counting can tackle a lot of object lifetime issues and you get to call delete (this). Fun times. See also:
http://en.cppreference.com/w/cpp/memory/shared_ptr
I am using boost 1.55 (io_service doc). I need to call the destructor on my io_service to reset it after power is cycled on my serial device to get new data. The problem is that when the destructor is called twice (re-trying connection), I get a segmentation fault.
In header file
boost::asio::io_service io_service_port_1;
In function that closes connection
io_service_port_1.stop();
io_service_port_1.reset();
io_service_port_1.~io_service(); // how to check for NULL?
// do I need to re-construct it?
The following does not work:
if (io_service_port_1)
if (io_service_port_1 == NULL)
Thank you.
If you need manual control over when the object is created and destroyed, you should be wrapping it in a std::unique_ptr object.
std::unique_ptr<boost::asio::io_service> service_ptr =
std::make_unique<boost::asio::io_service>();
/*Do stuff until connection needs to be reset*/
service_ptr->stop();
//I don't know your specific use case, but the call to io_service's member function reset is probably unnecessary.
//service_ptr->reset();
service_ptr.reset();//"reset" is a member function of unique_ptr, will delete object.
/*For your later check*/
if(service_ptr) //returns true if a valid object exists in the pointer
if(!service_ptr) //returns true if no object is being pointed to.
Generally speaking, you should never directly call ~object_name();. Ever. Ever. Ever. There's several reasons why:
As a normal part of Stack Unwinding, this will get called anyways when the method returns.
deleteing a pointer will call it.
"Smart Pointers" (like std::unique_ptr and std::shared_ptr) will call it when they self-destruct.
Directly calling ~object_name(); should only ever be done in rare cases, usually involving Allocators, and even then, there are usually cleaner solutions.
While writing a new vst-plugin using VSTGUI I'm really struggling with how to use the library, and most progress is made from guessing and debugging after (because there really is no documentation besides the million lines and ygrabit, which states little more than the obvious).
So far it's going good, but my last contribution to the project involved threads which made the design a little bit more problematic. Specifically, I'm working on a set of textlabels in a container (doing non-atomic operations) and these may (and obviously does) get destructed without my knowledge, when a user closes the window.
Even adding checks right before changing elements might still be a problem. So I actually need to control the lifetime of these objects (which is fine) except when they are shown in a CViewContainer, it automatically assumes ownership.
I have no idea how to write the backbone of the editor, so i used a program called VSTGUIBuilder for this, and appended (and basically rewrote) what i needed. However, since all 'views' you can work with requires either a parent or a systemwindow, you cannot instantiate any views/controls before reaching the AEffEditor::Open() function, which is called whenever your window is popped up.
And the AEffEditor::close() method is called whenever the window is closed. Now, the vstguibuilder put a
delete frame;
inside the AEffEditor::close() method which suggests you rebuild and dispense all resources on every open and close. Can this really be true? And if it is, is there no way i can protect my container's contents (which for details is a vector< CTextLabel *>) from getting deleted mid-function? It's no problem to dispose of it afterwards, I'm just worrying about segfaults while changing it.
Using mutexes and the such is really the last resort (if the call is coming from the host), I don't want to hang the host in any case if my code faults and never releases.
Edit:
I ended up finding a solution which is not so elegant, but works safely. Here's the code in the worker function:
while(bLock) {
Sleep(0);
}
bLock = true;
if(msgs.empty())
return;
/*
Prevent someone deletes our lines in close().
we create a copy of the container to be 100% sure
and increase the reference count, so we can safely
work with our own container and we 'forget' them
afterwards, so they will be deleted if needed.
This ensures that close AND open can be called
meanwhile we are working with the lines
*/
bDeleteLock = true;
// also the copy constructor should work as expected here
// since we are working with pointers, we still reference the same content.
auto copy_lines = lines;
for each(auto line in copy_lines) {
line->remember();
}
bDeleteLock = false;
...
for each(auto line in copy_lines) {
line->forget();
}
cont->setDirty();
bLock is another 'mutex' that protects a message queue, which this function will print out. bDeleteLock protects the process of copying the line container and 'remembering' them, and instantly releases if afterwards. Both are declared as volatile bools, shouldn't that be enough? Here's the close() method btw.
void CConsole::Close() {
// locking lines while copying them over in a container we can work with
while(bDeleteLock)
Sleep(0);
//waiting for bLock is not needed because it wont get deleted.
if(!visible) //if we are not visible it's our responsibility to remove the view
delete cont;
lines.clear();
}
Ahh, VSTGUI, that brings back some dark memories. ;) But seriously, yes, you will probably have to use a mutex to prevent the host from hanging. Having to instantiate everything when the window reopens seems kind of silly, but you can see many plugins do just that.
One potential workaround is to use a shared memory segment for cached view data, and then pass a reference to the location back to your plugin
Yes, its actually "or". I shall explain. I am developing helper classes for myself, like DirectXToolKit. For managing COMs I`m using Microsoft::WRL::ComPtr<T> (wrl.h).
struct Renderer
{
ComPtr<ID3D11Device> m_Device;
ComPtr<ID3D11DeviceContext> m_ImmContext;
}
When all the resources are destroyed, the instance of the structure above should be destroyed as well, but after the dtor is called, I am triggering the error in Microsoft::WRL::ComPtr<T>, when it tries to release the device or context.
I have implemented the dtor where I manually release m_Device and m_ImmContext, but unfortunately the last member I try to release always encounters an issue in the function
unsigned long InternalRelease() throw()
{
unsigned long ref = 0;
T* temp = ptr_;
if (temp != nullptr)
{
ptr_ = nullptr;
ref = temp->Release();
}
return ref;
}
here
ref = temp->Release();
When I succeed releasing the device first, the context triggers the error, and vice versa (! yes, when one of them was successfully released, the destuction of the second member fails). There was already a question like mine (destroy directx device and swap chain), but the window and swapchain are already destroyed, like the other dx resources. Have no clue why is this happening. Any ideas?
Sorry for my imperfect English :3
I have fixed this issue. The problem was I have not understood std::shared_ptr good enough (the function std::make_shared actually (about shared pointers and their allocation)):
I have created the pointer like:
Obj *ObjPtr = new Obj();
and then just:
SomeOtherState.SharedObj = std::make_shared<Obj>(*ObjPtr);
and didn`t destroy the ObjPtr afterwards. The data ObjPtr was pointing on was still in memory, after SomeOtherState was destroyed (and as far as I have understood the issue should have gone as well if I have used the std::shared_ptr ctor) .
Most likely it was because of this memory leak, but there was another thing I have changed: CoUninitialize call was made before the last COM pointer was destroyed but from MSDN: CoUninitialize came that its important (from the first para actually):
Closes the COM library on the current thread, unloads all DLLs loaded by the thread, frees any other resources that the thread maintains, and forces all RPC connections on the thread to close.
So I have replaced CoInitialize and CoUninitialize correspondently and the issue have gone. If someone had had the same troubles, this could somewhat be a solution (either or both the first and the second change I have made).
I should probably add "com" tags for my question
the problem MAY be somewhere when you obtain the ImmediateContext.
According to the documentation:
http://msdn.microsoft.com/en-us/library/windows/desktop/ff476529%28v=vs.85%29.aspx
The GetImmediateContext method increments the reference count of the immediate
context by one. Therefore, you must call Release on the returned interface pointer
when you are done with it to avoid a memory leak.
So I >>>guess<<< that you've forgot releasing the context somewhere so the Device release fails afterwards.
BTW: Make also sure that resources are ALWAYS released in reverse order.
I know very little about COM, and searching Google for COM somhow did not find COM at all (probably because it searched .com address instead).
We are using a video capturing hardware. Its SDK allows us to register a callback when a frame is captured. An object interface is passed as a parameter to that callback, and we can get the large buffer address (to the captured frame pixels) and other information by querying to that object.
Now, it looks like calling Release() does not actually delete the memory but decreases the reference count, and when the count reaches 0, it is deleted, right? So, about that large buffer address mentioned above, how about "delete"ing the buffer using the "delete" keyword?
It seems that our program (not written by me, and the person who wrote the program quit the company) copies the pointer to the buffer into some class but never calls any Release() in the callback. Later, the buffer is "delete'd in the class. It seems Release()ing the frame interface object also deletes the buffer. But are they the same?
COM somehow counts the reference but what happens if user's code just deletes that memory? I am sorry if my question is obscure. In short, is it safe to delete a buffer that was gotten from a COM object.
Simplified code: Suspicious situation
void mycallback(IFrame f)
{
char* buffer;
f->GetBuffer(buffer);
MyClass m(buffer);
...
}
MyClass::DeleteBuffer()
{
delete m_buffer;
}
When the code copies the frame buffer content into its own buffer then nothing special happened. The frame buffer is still owned by the COM code, the code's own buffer is still owned by that code. Do not delete the COM buffer, that will invoke undefined behavior when the COM code deletes it too. You should only ever call Release() on a COM interface pointer if you called AddRef() first. In a scenario like this, the AddRef() call was made by the COM code before it invoked the callback. And the Release() call will be made after the callback returns.
Seeing a frame getting copied in a callback is quite normal, the frame buffer normally only stays valid for the duration of the callback. So you have to copy it if you use it later.
If you are chasing a memory leak then this is not likely the culprit. If there was a reference counting problem on the frame buffer then the program couldn't last for more than a minute before having consumed all available memory.
Try to use this place operator delete, CoTaskMemFree
Dealing with COM interfaces is more trickier :-)
Make sure you match the IUnknown::AddRef() and IUnknown::Release() calls
As long as you are in the same context, you can delete the buffer explicitly, even though you got them from a COM interface. But make sure you nullify the pointer after deletion, so that there is no post handling issues.
MyClass::DeleteBuffer()
{
if(m_buffer)
{
delete m_buffer;
m_buffer = null;
}
}