Here's the (relevant) code for my pro::surface class:
/** Wraps up SDL_Surface* **/
class surface
{
SDL_Surface* _surf;
public:
/** Constructor.
** #param surf an SDL_Surface pointer.
**/
surface(SDL_Surface*);
/** Overloaded = operator. **/
void operator = (SDL_Surface*);
/** calls SDL_FreeSurface(). **/
void free();
/** destructor. Also free()s the internal SDL_Surface. **/
virtual ~surface();
}
Now the problem is that in my main function, the object destroys itself (and hence calls the destructor which dangerously free()s the SDL Video Surface!) before the real rendering begins.
int main(int argc, char** argv)
{
...
// declared here
pro::surface screen = SDL_SetVideoMode(320,240,16,SDL_HWSURFACE|SDL_DOUBLEBUF);
// event-handling done here, but the Video Surface is already freed!
while(!done) { ... } // note that "screen" is not used in this loop.
// hence, runtime error here. SDL_Quit() tries to free() the Video Surface again.
SDL_Quit();
return 0;
}
So my question is, is there any way to stop the pro::surface instance from destroying itself before the program ends? Doing memory management manually works though:
/* this works, since I control the destruction of the object */
pro::surface* screen = new pro::surface( SDL_SetVideoMode(..) );
/* it destroys itself only when **I** tell it to! Muhahaha! */
delete screen;
/* ^ but this solution uses pointer (ewww! I hate pointers) */
But isn't there a better way, without resorting to pointers? Perhaps some way to tell the stack to not delete my object just yet?
You violated the Rule of Three, bitch.
pro::surface screen = SDL_SetVideoMode(320,240,16,SDL_HWSURFACE|SDL_DOUBLEBUF);
Is equal to
pro::surface screen = pro::surface(SDL_SetVideoMode(320,240,16,SDL_HWSURFACE|SDL_DOUBLEBUF));
Now double free, because you violated the Rule of Three. So give your class a proper copy constructor/assignment operator, or disallow them and explicitly construct it properly.
Edit: This also explains why your pointer version works fine- because you don't invoke a copy.
Wrap the screen in a special wrapper, that pairs SDL_SetVideoMode with SDL_Quit instead of SDL_FreeSurface.
pro::screen screen(320, 240, 16, SDL_HWSURFACE | SDL_DOUBLEBUF);
// ...
And fix your copy ctor, obviously.
Related
I am trying to learn how to use gtkmm having got a basic grasp of C++ (I like a challenge!). I have been working my way through the tutorials (as well as other reading). I am trying to use the approach of using glade to design the UI and then write the code to do the work.
So I have built a very simple UI (window and button at the moment!). I am using the GTK::Builder to load the UI from file. I am dividing the code into classes and a main caller.
Here is the main.cpp
#include "hellowindow.h"
#include <gtkmm/application.h>
int main(int argc, char *argv[]) {
auto app = Gtk::Application::create(argc, argv, "org.gtkmm.example"); //creates a Gtk::Application object, stored in a Glib::RefPtr smartpointer, create() method for this object initializes gtkmm.
HelloWindow hw; // Create a HelloWindow object
return app->run(hw, argc, argv); // shows the HelloWindow object and enter the gtkmm main processing loop, will then return with an appropriate success or error code
}
here is the header for the HelloWindow class
#ifndef HELLOWINDOW_H
#define HELLOWINDOW_H
#include <gtkmm/application.h>
#include <gtkmm/applicationwindow.h>
#include <gtkmm/button.h>
#include <gtkmm/box.h>
#include <gtkmm/builder.h>
#include <glibmm/fileutils.h>
/* derive the class from Gtk::ApplicationWindow base class */
class HelloWindow : public Gtk::ApplicationWindow {
public:
/* Conctructor */
HelloWindow();
/* Destructor */
~HelloWindow() override;
protected:
/* Signal handlers: */
void on_button_clicked();
/* Member widgets: */
Gtk::Box *cont; // Container
Gtk::Button *pButton; // Pointer to a Button
Glib::RefPtr<Gtk::Button> display_btn; // Smart pointer to a Button
Glib::RefPtr<Gtk::Builder> builder; // Builder
};
#endif // HELLOWINDOW_H
and here is the class code:
#include "hellowindow.h"
#include <iostream>
HelloWindow::HelloWindow() : builder(Gtk::Builder::create()){
try {
/* load window from glade file */
builder->add_from_file("glade/simple.glade");
}
catch(const Glib::FileError& ex) {
/* catch file errors */
std::cerr << "FileError: " << ex.what() << std::endl;
return;
}
/* ui builder created successfully from file */
/* add a container to the builder */
builder->get_widget<Gtk::Box>("cont", cont);
builder->get_widget<Gtk::Button>("display_button", pButton);
pButton->signal_clicked().connect(
sigc::mem_fun(*this, &HelloWindow::on_button_clicked)
);
/* add the container to the application window */
add(*cont);
/* set some parameters for the window */
set_title("Simple Gtk::Builder Demo"); // set the window title
set_default_size(500, 500); // set the window size
show_all(); // show the window and all of the enclosed widgets
}
HelloWindow::~HelloWindow(){
}
void HelloWindow::on_button_clicked(){
std::cout << "Hello World" << std::endl;
}
This all works fine and I think I understand what is happening. However, I have seen a different approach to adding widgets at runtime (https://sodocumentation.net/gtk3/topic/5579/using-glade-with-builder-api). The difference is how the button object is declared. In the code above it is declared as a pointer to a button object in the line:
builder->get_widget<Gtk::Button>("display_button", pButton);
However, the website above uses an approach of a smartpointer to the button object:
display_btn = Glib::RefPtr<Gtk::Button>::cast_dynamic(builder->get_object("display_button"));
The second way of doing it seems less clear, specifically the cast_dynamic aspect, would someone please explain the difference between the two approaches?
I hope that I have included enough information.
Thank you
Martyn
First of all, to understand the difference, and since you are new to
C++, I would recommend reading on the following topics:
Dynamic memory allocation (new/delete)
Memory leaks
Casting
Templates
First approach: get_widget
With this approach, you are getting a raw pointer (as opposed to a smart
pointer) to a widget defined from the ui file. Example:
Gtk::Grid* pGrid = nullptr;
refXml->get_widget("mygrid", pGrid);
After this, pGrid points to a Gtk::Grid widget. Notice that no
casting is required, you immediately get a Gtk::Grid. This is because
the Gtk::Builder::get_widget method is a template method:
// T_Widget is like a placeholder for some widget type,
// like Gtk::Grid for example.
template <class T_Widget >
void Gtk::Builder::get_widget(const Glib::ustring& name,
T_Widget*& widget
)
Usually in C++, such
raw pointers may be dangerous because if they point to an object
allocated on the heap (usually using new), one must remember to use
delete on them when done, otherwise memory leaks will occur. In this
case, pGrid is indeed a raw pointer to an object allocated on the
heap, but the documentation states:
Note that you are responsible for deleting top-level widgets (windows
and dialogs) instantiated by the Builder object. Other widgets are
instantiated as managed so they will be deleted automatically if you
add them to a container widget.
so most of the time (i.e. if not a toplevel widget), you do not have
to call delete, but sometimes you do. This is because Gtkmm has facilities
to automatically delete destroyed objects. See Gtk::manage for
more information on this.
When or not to use delete may become hard as code grows, especially since
you do not have to always do it (it can become easy to forget).
Second approach: get_object
With this approach, you are getting a smart pointer (a Glib::RefPtr) to
an object and casting to the right type is required, hence the
cast_dynamic
// get_object returns a Glib::RefPtr<Glib::Object>, which is not a Glib::RefPtr<Gtk::Button>
// so a cast is performed. This works because Gtk::Button is a child class of
// Glib::Object.
display_btn = Glib::RefPtr<Gtk::Button>::cast_dynamic(builder->get_object("display_button"));
The advantage of this is that once the cast is performed,
you do not have to manage the object's memory. It is managed by the
smart pointer (i.e. the smart pointer will automatically call delete
for you. This is true even for "top level" widgets.
Note: the cast used here, cast_dynamic, is a Gtkmm specific cast which wraps a dynamic_cast.
My opinion
I would personally go with the second approach because you get automatic
memory management (even for top level widgets), and hence no memory leaks.
However, the code gets harder to read as you already noticed.
I am stuck trying to get a cv::Mat object from another class (third party code) into my main function.
I have a class:
FrameObserver.h
class FrameObserver : virtual public IFrameObserver
{
public:
FrameObserver( CameraPtr pCamera, FrameInfos eFrameInfos, ColorProcessing eColorProcessing );
cv::Mat m_ConvertImage;
// This is our callback routine that will be executed on every received frame
virtual void FrameReceivedLeft( const FramePtr pFrame );
virtual void FrameReceivedRight(const FramePtr pFrame);
void ProcessCvLeft(const FramePtr pFrame);
void ProcessCvRight(const FramePtr pFrame);
static cv::Mat FrameObserver::getCurrentFrame() { return currentFrame; }
private:
static cv::Mat currentFrame;
#ifdef WIN32
double m_dFrequency;
#endif //WIN32
};
}}} // namespace AVT::VmbAPI::Examples
FrameObserver.cpp
void FrameObserver::ProcessCvLeft(const FramePtr pFrame)
{
VmbUchar_t *pBuffer;
VmbUint32_t FrameWidth;
VmbUint32_t FrameHeight;
pFrame->GetWidth(FrameWidth);
pFrame->GetHeight(FrameHeight);
pFrame->GetImage(pBuffer);
ShowFrameInfos(pFrame);
IplImage *img1 = cvCreateImageHeader(cvSize(
FrameWidth,
FrameHeight),
IPL_DEPTH_8U,
1);
cvSetData(img1, pBuffer, img1->widthStep);
cv::Mat copyimageL = cv::cvarrToMat(img1);
currentFrame = copyimageL; //copies to currentFrame here
}
Then I have main.cpp:
cv::Mat Mainframe;
int main( int argc, char* argv[] )
{
//I need to pull the currentFrame Mat stream into the frame Mat above.
}
What is the best way to do this? I have tried:
FrameObserver fo;
cv::Mat test = fo.currentFrame;
But it gives me the following error:
no default constructor exists for class "FrameObserver"
Thank you.
As far as C++ goes, your mistake is that the class FrameObserver has no default constructor (i.e. a constructor that can be called without arguments). It's not defined explicitly, nor will it be generated, since another constructor has already been defined (see here). Thus, you can't write
FrameObserver fo;
Since this invokes the default constructor FrameObserver::FrameObserver() which (see above) is not present. Thus, you should create the FrameObserver object using the existing constructor with arguments FrameObserver::FrameObserver( CameraPtr pCamera, FrameInfos eFrameInfos, ColorProcessing eColorProcessing );
Now on to the actual problem. Since this class is a part of a supplied API, you shouldn't try to change it, rather learn to use it correctly. By the name of it, it appears to be an observer. Thus, you need to create an instance of it (a single one, at that), and carefully read the docs on how it's supposed to supply you frame data as a matrix. I don't know how exactly it works, but by common sense, since it's an "observer", it should automatically provide you with notifications about incoming frames. Again, have a close look at the documentation.
Important edit:
Here it is, look at the header:
// This is our callback routine that will be executed on every received frame
virtual void FrameReceivedLeft( const FramePtr pFrame );
virtual void FrameReceivedRight(const FramePtr pFrame);
By the looks of it, you are supposed to subclass FrameObserver and reimplement the two above functions. That means that the code to process or extract those frames must reside inside those routines in the subclass you're going to create.
Anyway, while the details may vary, the concept stays: the observer is going to call some methods on its own. You can only wait for it to call those methods and react accordingly. More precisely, you register your class object or function within the observer object, and then let the observer call those methods automatically. (It is said that you "subscribe to the notifications" provided by the observer).
I've been running into problems with a C++ program that I've been working on recently. Specifically, I've been working on a program that uses Qt's GUI framework and I've been running into errors that seem to be related to double-deletion of pointers and exception handling. The issue is that I feel like the API that I'm using works in a way that isn't exactly predictable and because of that, I'm running into a lot of errors that seem counter-intuitive. I'm not the most experienced C++ programmer in the world, so maybe there is some overall strategy for working with new APIs that I'm missing..
Here's an example: I typically always try to delete objects that I dynamically allocate with inside the same class. In other words, if I populate a pointer using the new keyword within a class' constructor or init function, then I usually make sure to delete the contents of that pointer in the class' destructor.
Here's an simplified example of the class definition for the class that was giving me problems [MyProject.h]:
#ifndef MYPROJECT_H
#define MYPROJECT_H
#include "QObject.h"
class QGuiApplication;
class QQmlApplicationEngine;
#define MYPROJECT MyProject::getInstance()
class MyProject : public QObject
{
Q_OBJECT
private:
explicit MyProject(QObject *parent = 0); //singleton..
MyProject(MyProject const&); //uncopyable..
void operator=(MyProject const&); //unassignable..
QGuiApplication * QtGUI;
QQmlApplicationEngine * QmlAppEngine;
public:
~MyProject(void);
/* Globally available function to get MyProject's singleton instance.
* You can use the "MYPROJECT" preprocessor macro for shorthand. */
static MyProject & getInstance(void)
{
static MyProject instance;
return instance;
}
int init(int argc, char * argv[]);
int exec(void);
signals:
public slots:
};
#endif
This is what my simplified main.cpp looks like:
#include "MyProject.h"
int main(int argc, char * argv[])
{
MYPROJECT.init(argc, argv);
return MYPROJECT.exec();
}
Here's the ctor and init() that I initially had for that class [MyProject.cpp]:
MyProject::MyProject(QObject *parent) :
QObject(parent) ,
QtGUI(NULL) ,
QmlAppEngine(NULL)
{
}
MyProject::~MyProject(void)
{
//segfault: debug points to both of these..
if (QtGUI) delete QtGUI;
if (QmlAppEngine) delete QmlAppEngine;
}
int MyProject::init(int argc, char * argv[])
{
QtGUI = new QGuiApplication(argc, argv);
QmlAppEngine = new QQmlApplicationEngine();
if(QtGUI && QmlAppEngine)
{
//segfault: debug points to this..
QmlAppEngine->load(QUrl( QStringLiteral("qrc:///MyProject.qml") ));
}
else return 1;
}
int MyProject::exec(void)
{
return QtGUI->exec();
}
So, my plan was: ctor initializes pointers to NULL, init() populates those pointers with new objects, and if those pointers are not null the dtor cleans them up with delete. But this code crashes with 2 segfaults, but even though I think I've narrowed it down, I'm not sure I understand why they're both happening.
(1) Segfault #1 is a crash on startup that points to the "QmlAppEngine->load()" call inside the init(). I was able to prevent the crash from occurring by wrapping that function call in exception handling code like this:
int MyProject::init(int argc, char * argv[])
{
QtGUI = new QGuiApplication(argc, argv);
QmlAppEngine = new QQmlApplicationEngine();
if(QtGUI && QmlAppEngine)
{
//exception handling prevents crash..
try
{
QmlAppEngine->load(QUrl( QStringLiteral("qrc:///MyProject.qml") ));
}
catch(int e)
{
std::cout << "Exception: " << e << std::endl;
return 1;
}
return 0;
}
else return 1;
}
I'm not very familiar with exception handling, as most of the code I've written so far has used int return-code style error handling. I'm guessing that the load function can throw an exception in certain situations, and not handling them can cause a crash. The program stopped crashing on start-up once I made this change, but strangely, it didn't seem to actually throw an exception as my 'cout' never output anything.. Something else that I don't understand is that this code is called without any exception handling code in the default setup for brand new Qt Projects that Qt Creator makes - for example, this is what you see when you start a new QtQuick2 project in QtCreator IDE:
#include "QGuiApplication"
#include "QQmlApplicationEngine"
int main(int argc, char * argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine();
//default Qt file calls this without issue though..
engine.load(QUrl( QStringLiteral("qrc:///MyQml.qml") );
return app.exec();
}
The only major different that I can see here is that the default code uses objects instead of pointers to objects. But, in this case, load runs fine without exception handling code and there is no segfault..
(2) The next issue is caused when my dtor calls the delete keyword on those two pointers. If I comment out those two lines, the program runs fine and closes without crashes or issues. This leads me to believe that the API has made these objects delete themselves later, which is causing a segfault due to double-deletion when I also explicitly call delete. But, in general, how can one know if the API that they're using is taking care of object deletion internally? And, if I can't tell whether or not an API specified object is being deleted automatically, should I take any extra measures (i.e.: use some kind of smart pointer, etc.)? Typically I make the assumption that I should delete any dynamically allocated objects in the destructor of the same class, but clearly that can backfire in situations like this.
So what steps can I take to work with the APIs that I use in a way that (a) prevents bugs and (b) allows me to make sure that resources are being freed correctly and exceptions are being handled?
It's hard to find the exact location of error by seeing the sample code you provided, your application must have large code base and does many things with memory. Qt is a well designed and fully documented framework (though some documentation are misleading or outdated), I suggest you to read properly the documentation about a specific item if you have confusion. Here are some general issues I guess you should know/consider when using Qt:
When creating an object on the heap of class that inherits QObject, if you pass a parent ( another QObject) in the constructor, then the child object is owned by parent and memory will be freed automatically by the parent object.
QObject is NO_COPYABLE, so if you inherit from it, you don't need to make copy ctor/assignment operator private. The compiler generated versions of these methods calls parent version (here QObject), hence your class is automatically un-copyable/assignable.
new by default throws bad_alloc exception if it fails instead of returning NULL. So either you use try-catch or change default behavior by using no_throw version of new (new(std::nothrow)), it will return nullptr on failure.
deleteing a NULL pointer will not cause any problem. However, if the pointer points to arbitrary location / contain garbage value, deleteing it will result in segfault.
By default engine.load is not used with exception handler, so there is a high chance it does not raise exception. Look closely in other areas of your code.
I think I must be "doing something wrong" here. I have a program using gtkmm. The main window for the program is a subclass of Gtk::Window and I have the bare bones of the application drawn out in Glade.
Here's an edited version of the main window's constructor:
template<class T>
static T*
get_widget (Glib::RefPtr<Gtk::Builder> builder, const Glib::ustring& name)
{
T* widget;
builder->get_widget (name, widget);
if (! widget) no_such_widget (name);
return widget;
}
app_window::app_window ()
{
Glib::RefPtr<Gtk::Builder> builder;
try {
builder = Gtk::Builder::create_from_file (installed_ui_name);
}
catch (const Glib::FileError& err) {
g_error ("Couldn't open UI definition file at %s",
installed_ui_name);
throw;
}
// main_box is a std::unique_ptr<Gtk::Widget>, a field of app_window.
//
// This works fine: the Gtk::Box gets added as the main child of this
// app_window and survives until the app_window is destroyed.
main_box.reset (get_widget <Gtk::Box> (builder, "main-box"));
add (* main_box);
auto accel_group = get_accel_group ();
// This doesn't work so well
//
// menu_quit is a Gtk::MenuItem*. The object seems to be actually
// constructed for the call to builder->get_widget, because its existence
// stops the menu item from being finalized at the end of the application.
auto menu_quit (get_widget<Gtk::MenuItem> (builder, "menu-quit"));
menu_quit->add_accelerator ("activate", accel_group,
GDK_KEY_q, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
using std::bind;
menu_quit->signal_activate ().connect (bind (& app_window::on_close, this));
show ();
}
When setting up the window, I want to register various signal handlers for menu items etc. (the menu_quit widget in the example is just one of them). To do so, I think I need to use builder->get_widget() to get hold of an object to talk about.
The problem is that I've now got an instance of (a subclass of) Gtk::Widget and I don't know what to do with it. If I call delete on the pointer, the widget doesn't appear in the application, but no other problems happen. That's a bit confusing: I would expect either no effect or a segmentation fault (depending on whether something else thought it owned the object or not).
If, on the other hand, I leak the pointer, assuming that object will be owned by the container into which main_box has been added, I get a memory leak. In particular, menu_quit's underlying gtk_image_menu_item doesn't get finalised because the reference count is one too high. (I can check easily enough that with GDB)
A "solution" is to store a pointer to each object that I get with builder->get_widget as a field in the app_window and then delete it in the destructor (automated with std::auto_ptr or std::unique_ptr). But that's really horrible: I don't want to have to write out a field for every single menu item! Avoiding that sort of nonsense was the whole point of using GtkBuilder in the first place!
Assuming that this isn't a bug (gtkmm 3.12.0, if that's relevant), I assume I'm just doing it wrong. How is an application supposed to do this?
As per suggestion at a job interview I had recently, I was advised to research into the unique_ptr functionality of C++11, as a means of automated garbage collection. So I'm using an older project and replacing my raw pointers to objects created with the 'new' keyword, with unique_ptrs. However I think I have arrived at an issue of ownership.
In my mainclass.cpp (posted below) please turn your attention to the init function and the 3 unique_ptrs to new-instantiated objects I have created. Named "bg","bg2", and "theGrid".
(The commented out declarations below them are how they used to be done, and switching back to this method, the program runs just fine.)
However, using the unique_ptrs, the line in the function void display():
theGrid->doGridCalculations();//MODEL
generates an access violation. This is also the first time in the sequence that any of the pointed objects are dereferenced, which leads me to believe that ownership of the unique_ptr is already lost somewhere. However, the unique_ptrs themselves are never passed into another function or container, and remain in the scope of the mainclass.cpp and therefore I've seen no opportunity to use std::move(theGrid) in order to transfer ownership to where it needs to be.
Mainclass.cpp:
#include <stdio.h>
#include <GL/glut.h>
#include <math.h>
#include "Block.h"
#include "dStructs.h"
#include "Grid.h"
#include "Texture.h"
#include "freetype.h"
#include <Windows.h>
//////////////////////////////////////////////////////
///Declare a couple of textures - for the background
//////////////////////////////////////////
Texture* bg;
Texture* bg2;
//and theGrid
Grid* theGrid;
/////////////////////////////////////////////////
///Declare our font
/////////////////////////////////////////////////
freetype::font_data scoreFont;
/////////////////////////////////////////////////////////
//Initialize the variables
///////////////////////////////////////////////////////
typedef dStructs::point point;
const int XSize = 755, YSize = 600;
point offset = {333,145};
point mousePos = {0,0};
void init(void)
{
//printf("\n......Hello Guy. \n....\nInitilising");
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0,XSize,0,YSize);
//////////////////////////
//initialise the fonts
/////////////////////////
try{
scoreFont.init("Visitor TT2 BRK Regular.ttf", 20);
} catch (std::exception &e) {
MessageBox(NULL, e.what(), "EXCEPTION CAUGHT", MB_OK | MB_ICONINFORMATION);
}
///////////////////////////////////////////////////////////////
///bg new MEMORY MANAGED EDITION
//////////////////////////////////////////////////////////////////
unique_ptr<Texture> bg(new Texture(1024,1024,"BackGround.png"));
unique_ptr<Texture> bg2(new Texture(1024,1024,"BackGround2.png"));
unique_ptr<Grid> theGrid(new Grid(offset));
/////////////////////////////////////////////////
/// Old bad-memory-management style of pointed objects
/////////////////////////////////////////////////
//bg = new Texture(1024,1024,"BackGround.png");
//bg2 = new Texture(1024,1024,"BackGround2.png");
//theGrid = new Grid(offset);
glClearColor(0,0.4,0.7,1);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);//activate the alpha blending functionality
glEnable(GL_BLEND);
glLineWidth(2); // Width of the drawing line
glMatrixMode(GL_MODELVIEW);
glDisable(GL_DEPTH_TEST);
//printf("\nInitialisation Complete");
}
void myPassiveMouse(int x, int y)
{
//Stupid OGL coordinate system
y = YSize - y;
mousePos.x = x;
mousePos.y = y;
printf("\nthe mouse coordinates are (%f,%f)",mousePos.x, mousePos.y);
}
void displayGameplayHUD()
{
///////////////////////////////
//SCORE
//////////////////////////////
glColor4f(0.7f,0.0f,0.0f,7.0f);//set the colour of the text
freetype::print(scoreFont, 100,400,"SCORE: ");
glColor4f(1.0f,1.0f,1.0f,1.0f);//Default texture colour. Makes text white, and all other texture's as theyre meant to be.
}
//////////////////////////////////////////////////////
void display()
{
////printf("\nBeginning Display");
glClear(GL_COLOR_BUFFER_BIT);//clear the colour buffer
glPushMatrix();
theGrid->doGridCalculations();//MODEL
point bgLoc = {XSize/2,YSize/2};
point bgSize = {XSize,YSize};
bg2->draw(bgLoc,bgSize);
theGrid->drawGrid();//DISPLAY
bg->draw(bgLoc,bgSize);
if(theGrid->gridState == Grid::STATIC)
{
theGrid->hoverOverBlocks(mousePos);//CONTROLLER
}
displayGameplayHUD();
glPopMatrix();
glFlush(); // Finish the drawing
glutSwapBuffers();
////printf("\nFresh Display Loaded");
glutPostRedisplay();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv); // GLUT Initialization
glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE); // Initializing the Display mode
glutInitWindowSize(755,600); // Define the window size
glutCreateWindow("Gem Miners"); // Create the window, with caption.
init(); // All OpenGL initialization
//-- Callback functions ---------------------
glutDisplayFunc(display);
//glutKeyboardFunc(mykey);
//glutSpecialFunc(processSpecialKeys);
//glutSpecialUpFunc(processSpecialUpKeys);
glutMouseFunc(mymouse);
glutPassiveMotionFunc(myPassiveMouse);
glutMainLoop(); // Loop waiting for event
}
I think the ownership needs to be transferred at some point, but I don't know where.
Thanks in advance,
Guy
These are global raw pointers:
Texture* bg;
Texture* bg2;
//and theGrid
Grid* theGrid;
These are completely unrelated unique_ptrs, local to the init function.
unique_ptr<Texture> bg(new Texture(1024,1024,"BackGround.png"));
unique_ptr<Texture> bg2(new Texture(1024,1024,"BackGround2.png"));
unique_ptr<Grid> theGrid(new Grid(offset));
When the unique_ptrs go out of scope, they are destroyed. The objects that they point to are also destroyed, because that is what unique_ptr does in its destructor. At no point in that process were the global raw pointers involved with the debacle. They were hidden by the local unique_ptrs of the same name.
You should change your global raw pointers to unique_ptrs. Then you can set them (don't re-declare them) in the init function like this:
bg.reset(new Texture(1024,1024,"BackGround.png"));
bg2.reset(new Texture(1024,1024,"BackGround2.png"));
theGrid.reset(new Grid(offset));
The unique pointers that you create in your init function do not modify the pointers declared at file scope, the ones at file scope are default-initialised to 0 or nullptr (I'm not that well versed at C++11 so I'm not sure which).
What you're doing in the init function is creating three new objects with names that shadow the ones at file scope, so when you go to use the ones at file scope you get an access violation because they are never set to point at anything valid.
Your unique_ptr<Grid> in init is local to that function. The unique_ptr<Grid> will go out of scope at the end of the function, destroying itself and the Grid it owns. It seems like you want to actually have a global object unique_ptr<Grid> theGrid; which replaces the Grid* theGrid; you've got at the momement. Then in init you can do:
theGrid.reset(new Grid(offset));
The theGrid that is being accessed in display is the global theGrid of type Grid*.
The exact same is true for the other unique_ptrs you've tried to create.
Of course, rather than a global object, it would be much better to be passing these objects around, but your use of GLUT makes that a bit painful.