• Advertisement
Sign in to follow this  

How dangerous is returning a initialized pointer in C++?

This topic is 1280 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

A quick question on how danagerous this would actually be...

 

In a static library i have this function that will be the starting base for my engine.

_declspec(dllexport) struct EngineAPI {

public: 
EngineAPI(); 
~EngineAPI();

EngineAPI *Create();

private:

};
//-- EngineAPI.cpp
EngineAPI *EngineAPI::Create() {
EngineAPI *engine = new EngineAPI();
return engine;
}


//-- In Dynamic Library to be interpoled in C#.
EngineAPI *gEngine;
void CreateEngine() {
gEngine = gEngine->Create();
if(gEngine == nullptr) {
//-- we have problem
}
else {
//-- We are good to go.
 }
}

I just want to know because it's working for me but on this other question\answer forum they literally jumped on me saying that code was dangerous and absolutely horrendous. I'm just wanting to know why they would consider that?

Share this post


Link to post
Share on other sites
Advertisement

Okay, I don't quite understand why you are doing things this way.  You declare a global pointer, then use it to initialize the same global pointer.  Why?  if gEngine is not allocated, then calling ::Create is just going to crash.

 

I use C++ myself, but this is how I would do it instead.

void CreateEngine()
{
   gEngine = new EngineAPI();

   /* Do error checking here */
}

What you are doing appears to be quite unnecessary.  Is there a particular reason you want your engine this way?

 

Shogun.

 

EDIT: One more detail.  If you are returning an initialized pointer from C++ to C#, that is a bad idea.  C++ has it's own code routines for initializing a pointer via "new", whereas C# is undoubtedly different, so calling delete on a C++ pointer in C# is potentially dangerous.  Think of it this way, would you use malloc() for a C pointer, then deallocate it with delete in C++?  That is a VERY bad idea, and I would not recommend it.

Edited by blueshogun96

Share this post


Link to post
Share on other sites

Okay, that would make a lot of sense! Well inside the API I wanted to have the engineAPI do most most of the handling. It's not it's crashing - it's just the correctedness of good programming is why the people on that q/a forum was getting hysterical about. I get what you're saying. For instance I wanted everything to be based from the engine or to be branching from the engine.

 

So, I believe from going back and forth to the static library to the dynamic library for interloping to C# I'm getting a bit mixed up. An API\SDK are just tools either interfaces, abstract classes and a like - am I correct maybe not on the terminology but the basis of it.

 

Maybe my brain isn't making sense lol! You know how NVIDIA creates a physics scene I don't recall using a new keyword. I switched to bullet physics because I can't compile the nvidia physics library along with my static library file then import the static library into my dynamic library.

 

Yeah you're right it doesn't make much sense why i would be calling the Create() function because it's just like saying the new keyword like you mentioned.

Share this post


Link to post
Share on other sites

Your Create function doesn't check for a previously allocated pointer. You need to check for a valid pointer and return that if it exists, otherwise multiple calls will result in memory leaks, or worse.

for( int i=0; i < 1000; i++) EngineAPI::Create();

Share this post


Link to post
Share on other sites

I thought I just ask because the stackexchange site wasn't so happy about my question. Instead of the Create() function I just am using the EngineAPI *engine = new APIEngine(). approach. It's not too bad just have to remember to place a delete engine when I'm done. Which I've already have done when the editor closes. When it gets down to the creating the game finally - I'll make sure I check every possibly memory leak. I know how it is to open a program then to close it - then to reopen the program again and it hangs a bit or suddenly just start spitting out exceptions.

 

That's one more thing I've been working on keeping sure everything is leak free and code is readible so i can understand it when I'm looking back at the code for any improvements.

Share this post


Link to post
Share on other sites

Also what came to mind is if I stuck with the whole Create function and when I need to dispose it - there will possibly be a memory leak most definately. As Buckeye stated. It's always to stay safe than sorry later on when testing on other platforms.

Share this post


Link to post
Share on other sites

 

You wouldn't need to call delete if you would do:

auto engine = std::make_unique<APIEngine>();

I haven't got to smart pointers yet but still I would need the engine pointer for later referencing until the program closes.

Share this post


Link to post
Share on other sites

 

 

You wouldn't need to call delete if you would do:

auto engine = std::make_unique<APIEngine>();

I haven't got to smart pointers yet but still I would need the engine pointer for later referencing until the program closes.

 

What I'm trying to do is create a proper framework for the Engine's API. The Engine API is at the parent or root node for instance and all it's counter parts are in the children node. Graphics API is under the Engine's API under the Graphic's API goes in the model rendering and so on and so on. A neat looking heiarchy tree. My framework now is going through re-working.

Share this post


Link to post
Share on other sites

 

 

You wouldn't need to call delete if you would do:

auto engine = std::make_unique<APIEngine>();

I haven't got to smart pointers yet but still I would need the engine pointer for later referencing until the program closes.

 

 

That's what std::unique_ptr::get() is for: to get the pointer to the object managed by the unique_ptr without releasing ownership of the pointer.

 

This tutorial about C++11 smart pointers is worth a read.

Share this post


Link to post
Share on other sites

 

 

 

You wouldn't need to call delete if you would do:

auto engine = std::make_unique<APIEngine>();

I haven't got to smart pointers yet but still I would need the engine pointer for later referencing until the program closes.

 

 

That's what std::unique_ptr::get() is for: to get the pointer to the object managed by the unique_ptr without releasing ownership of the pointer.

 

This tutorial about C++11 smart pointers is worth a read.

 

Actually, I think I'm starting to fall in love with smart pointers! I always loved the smart ones. At first it was confusing because I wanted to get the functions I made within that class or struct - you know? I never knew how until I read the tutorial about C++ 11 smart tutorials. I was a bit naive about the std::shared_ptr. So, I tried it on the graphics device struct and there was no worries about ever freeing up the initialized class - just had to dispose the COM objects created by DIrectX. Pretty sweet!

Share this post


Link to post
Share on other sites

What are you trying to accomplish with this design?  You could just as easily stack allocate the EngineAPI object in your main function, and then pass around a pointer to that object.  This would control the timing of the object creation, it would trivially ensure that the object is destroyed when it goes out of scope, and there is no question of ownership or shared ownership.  I usually default to the simplest solution with the fewest strings attached to it, and unless you have a good reason to hide the object creation behind a factory/singleton hybrid method, I think you are unnecessarily complicating this!

ALl I'm trying to do is making the framework a bit more tidy then I think it is. In a framework shouldn't everything be interchangablly connected as in a car engine or even a tree? I'm probably like you said am putting too much thought in this framework design. I don't think the main ENgineAPI will be a singleton class. The way I see it as of right now - everything's fine I just have a habit of reworking on or redesigning on idea I have.

Share this post


Link to post
Share on other sites


Actually, I think I'm starting to fall in love with smart pointers! I always loved the smart ones. At first it was confusing because I wanted to get the functions I made within that class or struct - you know? I never knew how until I read the tutorial about C++ 11 smart tutorials. I was a bit naive about the std::shared_ptr. So, I tried it on the graphics device struct and there was no worries about ever freeing up the initialized class - just had to dispose the COM objects created by DIrectX. Pretty sweet!
Smart pointers are a great tool, but remember what they are implying - they implement ownership semantics for the object they are wrapping.  If you have a shared pointer to your engine API object, then you are essentially saying that any object that has a reference to it is also an owner of it.  That means that if you have one outstanding reference, the object will not be destroyed.

 

That can be what you want in many cases, but the usage you point out above is not really one of those (at least in my humble opinion!).

Share this post


Link to post
Share on other sites

 

What are you trying to accomplish with this design?  You could just as easily stack allocate the EngineAPI object in your main function, and then pass around a pointer to that object.  This would control the timing of the object creation, it would trivially ensure that the object is destroyed when it goes out of scope, and there is no question of ownership or shared ownership.  I usually default to the simplest solution with the fewest strings attached to it, and unless you have a good reason to hide the object creation behind a factory/singleton hybrid method, I think you are unnecessarily complicating this!

ALl I'm trying to do is making the framework a bit more tidy then I think it is. In a framework shouldn't everything be interchangablly connected as in a car engine or even a tree? I'm probably like you said am putting too much thought in this framework design. I don't think the main ENgineAPI will be a singleton class. The way I see it as of right now - everything's fine I just have a habit of reworking on or redesigning on idea I have.

 

I'm not saying it is right or wrong - I'm just saying that it would be simpler and more safe if you stack allocate the object instead of the method you showed above.  There is no more or less dependencies on the implementation of your object in either method, so like I mentioned above, I would tend toward the simplest alternative.

Share this post


Link to post
Share on other sites

 


Actually, I think I'm starting to fall in love with smart pointers! I always loved the smart ones. At first it was confusing because I wanted to get the functions I made within that class or struct - you know? I never knew how until I read the tutorial about C++ 11 smart tutorials. I was a bit naive about the std::shared_ptr. So, I tried it on the graphics device struct and there was no worries about ever freeing up the initialized class - just had to dispose the COM objects created by DIrectX. Pretty sweet!
Smart pointers are a great tool, but remember what they are implying - they implement ownership semantics for the object they are wrapping.  If you have a shared pointer to your engine API object, then you are essentially saying that any object that has a reference to it is also an owner of it.  That means that if you have one outstanding reference, the object will not be destroyed.

 

That can be what you want in many cases, but the usage you point out above is not really one of those (at least in my humble opinion!).

 

I'll have to keep that in mind! I don't want this to drag on further because it wasn't my intention. If I'm going to use a smart pointer it may as well be on something that I want to get rid of when it's out of scope or something that isn't referenced a lot of times?  

Share this post


Link to post
Share on other sites

All the discussion about smart pointers is great. However, it is possible to make the original code safe (or safer) without using smart pointers. You need to use a static function for Create, instead of a standard function. A static function is part of the class, but doesn't access any of the class members, and thus is safe to use even if you don't have an instantiated object. So, change:

EngineAPI *Create();

To:

static EngineAPI *Create();

And change:

gEngine = gEngine->Create();

To:

gEngine = EngineAPI::Create();

Again, all the smart pointer and ownership discussion is great, but static Create functions are a pattern you'll often see, and are perfectly valid.

 

Geoff

Edited by gdunbar

Share this post


Link to post
Share on other sites
To make things even better, you could use Meyers Singleton (you're trying to accomplish a singleton, are you not?). It has the advantage of being thread-safe (in C++11), plus: you don't have to use dynamic memory to allocate it, you don't have to always check if you have already allocated it (gEngine != null) and you don't have to deallocate it. It automatically calls your destructor upon program exit.
 
static EngineAPI * EngineAPI::Create() {
  static EngineAPI engineAPI;
  return &engineAPI;
} 

Share this post


Link to post
Share on other sites

 

You wouldn't need to call delete if you would do:

auto engine = std::make_unique<APIEngine>();

Although the intent is good, that is usually not a great idea (just like deleting the pointer in general isn't). You should always have a Create function paired with a Destroy (or similarly named) function. That one can be called from a custom deleter if you'd like to use unique_ptr, of course.

 

Why?

 

First, it makes opaque what's going on. It allows you to later change how the library starts up and tears down without having to modify client code. Even if Destroy simply calls delete for now, you still want to encapsulate that. You can change whatever happens behind the scenes without asking someone.

 

Second, and more importantly, on some systems (notably one major desktop operating system), shared libraries have (or may have) their own heap.

Which means that you may end up allocating the Engine object on one heap and attempt to free it on another, which the runtime might swallow silently, or it might answer with a debug assert, or something different. In any case, it's not a pretty thing, even if it "works fine".

Share this post


Link to post
Share on other sites


Second, and more importantly, on some systems (notably one major desktop operating system), shared libraries have (or may have) their own heap.
All the more reason for stack allocation!

Share this post


Link to post
Share on other sites

wow I got back a lot of great feedback from everyone! samoth this makes sense because the library file could create an allocated memory address at a certain spot in memory and when sometimes the DLL retreives it - it says causes an exception of unable to read or write to memory location. This is happening to the font system that I got from Rastertek. I plan on reduing the font system because if I leave the room for one minute and I have important level detail I want to save- then my work is done due to the exception. Happens when I'm mapping the dynamic buffer. I'll get to that later on not on this post though.

 

As of now I'm continuing reading and doing more research on how I can improve upon my C++ skills with less mistakes. If someone's playing my game and it suddenly burps up a exception - it's going to leave many customers unhappy and unwilling to buy from me again. That I do know that's why I'm taking every precaution and every step to assure my skills become better sharpened.

Share this post


Link to post
Share on other sites

One thing I know about business is a customer that is unhappy won't return again and will have harder time trusting the next product. I understand games like Rage have bugs that left a lot of players aggravated. Some logical errors such as collision detection (e.g. going through a rock and being stuck in a rock) are something things that aren't avoidable. Or spawning at the wrong time and wrong place like enemies in the grown - caught that glitch in Assassin's Creed 4.  However, if I have my game constantly crashing on the players - my head will be on the platter and I may as well dig myself into a cave; so to speak.

 

I'm not saying I'm a total noobie but I do need to sharpen my skills like a knife that needs sharpen every once in a while - if I'm going to compete in the game industry.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement