Hi Iam working on a cocos2dx framework with cpp. I am facing memleak on a function where I use new keyword to initialize a class. Here I have a base class for all the popup in my game. I would like to make a popup from the base popup class inheriting from it. And adding the new popup as a child of a scene. The problem is when I initialize the new popup class on the stack, I couldnot call other functions which is in the new popup class. So i initialized my new popup class in heap using new keyword. Iam also deleting the instance on a function called close popup. I also saw that when clearing Iam calling the delete on the correct pointer. But my precommit says thats a memeleak. Can someone sugeest ideas? Here's my code
# Newpopup.cpp extends BasePopup
views::BasePopup* NewPopup::createPopup() {
popup = BasePopup::createPopup(Size(400, 500));
return popup;
}
void NewPopup::cleanPopup() {
popup->removeFromParent();
delete this;
}
Adding the new popup to a scene in another Scene class
# Adding to scene
void MainScene::getNewPopup() {
NewPopup* NewPopup = new NewPopup();
this->addChild(NewPopup);
}
Here am I doing the correct delete?
Related
I am running into the following issue:
Users presses "Ctrl+N" which goes into function MainWindow::newAction()
In MainWindow::newAction(), create a QDialog dlg(centralWidget()) and call dlg.exec()
While dlg is open, users pressed "Ctrl+N" again
The result is that dlg never gets deleted (it will only get deleted once centralWidget() gets deleted).
The call stack is something like this:
MainWindow::newAction ()
...
MainWindow::newAction()
I am wondering how to handle this case. I want all of the local dialog variables from the first call to newAction() to be deleted by the time we go into the function newAction() again.
You also can try something like this:
void MainWindow::newAction() {
const auto dialog = new MyDialog(centralWidget());
// When user will close the dialog it will clear itself from memory
connect(dialog, &QDialog::finished, [dialog]() {
dialog->deleteLater();
});
dialog->exec();
}
However, a good move would be to stop user from summoning more QDialogs than a single one, given that this one is a modal dialog(might be a good idea to keep this dialog pointer as a class member and check is it on screen already before calling exec() on it.
If i understood the question right, you want one dialog to be opened and want to delete it before a new dialog request comes in?
If that's the case you can do following:
In MainWindow.h declare QDialog *dlg = nullptr
In your MainWindow.cpp newAction() function you can do following:
void newAction()
{
if(dlg != nullptr)
{
dlg->close();
dlg->deleteLater();
//or
//dlg->destroy(); // this will immediately free memory
}
dlg = new QDialog(centralWidget());
...
//dlg->exec(); // This will automatically make QDialog modal.
dlg->show(); // This will not make a QDialog modal.
}
I hope this will help. Remember QDialogs when displayed with exec() they automatically behave as Modal window. show() will make it non-modal.
Coming from making single-page applications with the visual WYSISWYG editor in JUCE, I'm having a bit of trouble figuring out how to invoke new windows (outside of the main GUI window). I made a test application that just has a small minimal main GUI that I created with the visual editor. It has a button "Make New Window." My goal is to be able to click that button and have a new window pop up and that this new window is a JUCE "GUI component," (AKA, the graphical / visual GUI editor file). Now, I actually have sort of achieved this, however, its throwing errors and assertions, so it would be great to get a very simple, step-by-step tutorial.
I studied the main.cpp file that the Projucer automatically created in order to get a feel for how they are creating a window. Here's what I did.
1) In my project, I added a new GUI Component (which becomes a class) and called it "InvokedWindow."
2) In my main GUI component class header, I added a new scoped pointer of type InvokedWindow: ScopedPointer<InvokedWindow> invokedWindow;
3) I created a new button in the main GUI editor called "Make New Window" and added this to the handler code:
newWindowPtr = new InvokedWindow; so that any time the button is hit, a new object of type InvokedWindow is created.
4) In the InvokedWindow class, in the constructor, on top of the automatically generated code, I added:
setUsingNativeTitleBar (true);
setCentrePosition(400, 400);
setVisible (true);
setResizable(false, false);
Which I sort of got from the main file of the JUCE application.
I also added a slider to this new window just to add functionality to it.
5) I added an overloaded function to let me close the window:
void InvokedWindow::closeButtonPressed()
{
delete this;
}
So, now when I run the app and click the make new window button, a new window does pop up, but I get an assertion:
/* Agh! You shouldn't add components directly to a ResizableWindow - this class
manages its child components automatically, and if you add your own it'll cause
trouble. Instead, use setContentComponent() to give it a component which
will be automatically resized and kept in the right place - then you can add
subcomponents to the content comp. See the notes for the ResizableWindow class
for more info.
If you really know what you're doing and want to avoid this assertion, just call
Component::addAndMakeVisible directly.
*/
Also, I'm able to close the window once and hit the button in the main GUI to create another instance of a newWindow, but closing it a second time leads to an error:
template <typename ObjectType>
struct ContainerDeletePolicy
{
static void destroy (ObjectType* object)
{
// If the line below triggers a compiler error, it means that you are using
// an incomplete type for ObjectType (for example, a type that is declared
// but not defined). This is a problem because then the following delete is
// undefined behaviour. The purpose of the sizeof is to capture this situation.
// If this was caused by a ScopedPointer to a forward-declared type, move the
// implementation of all methods trying to use the ScopedPointer (e.g. the destructor
// of the class owning it) into cpp files where they can see to the definition
// of ObjectType. This should fix the error.
ignoreUnused (sizeof (ObjectType));
delete object;
}
};
This is all a bit over my head. I was figuring it wouldn't be too bad to be able to create a new window, via a button. A new window that I could edit with the graphical GUI editor, but I'm not able to fully figure it out all on my own, through I did try. Could anyone post a step-by-step guide to doing this the correct way? I did post this at the JUCE forums, but due to my lack of GUI programming, I was unable to understand the solutions posted (my own fault), so I'm hoping to get a very simple guide to this. It would be very much appreciated. Thank you.
I figured it out. I needed to create:
A new GUI component (Remember, this is the visual editor in JUCE)
A class (I called it BasicWindow, based on the JUCE demo code) that acts as a shell to run this new window and holds the GUI component.
A JUCE SafePointer that makes a new object of type BasicWindow whenever the button is clicked and sets the attributes to that window.
Here is my code:
Referring to line 3) Inside the handler section of the button to create the new window:
basicWindow = new BasicWindow("Information", Colours::grey, DocumentWindow::allButtons);
basicWindow->setUsingNativeTitleBar(true);
basicWindow->setContentOwned(new InformationComponent(), true);// InformationComponent is my GUI editor component (the visual editor of JUCE)
basicWindow->centreWithSize(basicWindow->getWidth(), basicWindow->getHeight());
basicWindow->setVisible(true);
Referring to line 2) A .cpp file that defines what the BasicWindow is:
#include "../JuceLibraryCode/JuceHeader.h"
class BasicWindow : public DocumentWindow
{
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BasicWindow)
public:
BasicWindow (const String& name, Colour backgroundColour, int buttonsNeeded)
: DocumentWindow (name, backgroundColour, buttonsNeeded)
{
}
void closeButtonPressed() override
{
delete this;
}
};
And referring to line 1) Make the GUI editor component, which this is easy to do. You just right add a new file in the JUCE file manager. "Add New GUI Component," then visually add all your elements and handler code.
My biggest issue was that I was using a JUCE ScopedPointer, so after deleting the object, the pointer pointing to it wasn't being set back to NULL. The SafePointer does this. If any more explanation is needed, I'm happy to help, as this was terrible for someone with not much GUI development "under his belt."
Actually im having 2 Qwidgets say "Widget" , "NewWidget". I'm calling "NewWidget" in "Widget" keypress event and viced versa,
void Widget::keyPressEvent(QKeyEvent *qv)
{
// i want to delete "Widget" here before i call "NewWidget"
NewWidget *newWidget = new NewWidget();
newWidget->setStyleSheet("background-color:black;");
newWidget->setGeometry(0,0,640,480);
newWidget->show();
}
I want to delete or destroy the "Widget" before calling "NewWidget"
Try the following
this->deleteLater();
It will attempt to destroy the widget when the function exits.
It sounds dangerous/bad to destroy the current widget when you are busy inside a member function of the widget that you want to destroy. Try the above code but otherwise think about redesigning your interactions.
I want to update a user interface when I clicked a button. However, I'm not using a direct way inside CProjectDlg. I have a CMain class which will handle the operation.
Here is my code:
ProjectDlg.cpp
void CProjectDlg::OnBnClickedButton1()
{
CMain *ptr = new CMain();
ptr->Click();
CString test = m_edit1;
}
Main.cpp
void CMain::Click()
{
CProjecttDlg *ptr = new CProjectDlg();
ptr->m_edit1.SetString(L"This is a test.");
}
In the debug mode, I found the address of m_edit1 is not same. So the function is useless.
I need to pass the same address of m_edit1 to the Click() function. How do I do that?
Thank you.
Each time you click, you create a new dialog.
CProjecttDlg *ptr = new CProjectDlg();
What you must do is to create it just once (maybe at CMain constructor? or the first time click is accessed). To store its value, just make ptr a member of CMain(define in .h, and so on) instead of a local variable.
You have a problem there. You are calling CMain::Click fron a CProjectDlg instance, but create a new instance of CProjectDlg inside CMain::Click, and set the edit box in that new dialog, not in the original one.
I don't know exactly what you are trying to do, but one thing that could work is to pass a pointer to the dialog to the CMain constructor, and then in CMain::Click use it ot set the edit box. Something like this:
//CMain.h
class CMain
{
public:
CMain(CProjectDlg*);
Click();
protected:
CProjecDlg* m_Dlg;
}
// CMain.cpp
CMain::CMain(CProjectDlg* dlg)
{
m_Dlg = dlg;
}
CMain::Click()
{
m_Dlg->m_edit1.SetString(L"This is a test.");
}
Apart from that, I don't know if it would be necessary to create a new instance of CMain every time the user clicks the bottom.
And finally, the possible solution I've provided might work, but it might also not be "correct". Without more details as to what you are trying to do, there's not much more I can help you with, though.
Lets say in a dialog, we dynamically create a variable number of CWnds... like creating a and registering a CButton every time the user does something/
Some pseudo-code...
class CMyDlg : public CDialog
{
vector<CWnd *> windows;
void onClick()
{
CButton *pButton = new CButton(...);
//do other stuff like position it here
windows.push_back(pButton);
}
}
Do I need to explicitly delete them or will MFC do it? If I have to, would it be in the destructor as normal, or are there any special things to avoid breaking MFC... making sure I don't delete the objects while the HWNDs are still in use for example?
CButton *pButton = new CButton(...);
These are C++ objects, which needs to be deleted explicitly. (Where as Main frame windows and Views are self destructed).
You can refer the detailed answer ( by me) Destroying Window Objects