Jump to content

  • Log In with Google      Sign In   
  • Create Account

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


Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.


  • You cannot reply to this topic
23 replies to this topic

#1   Members   

805
Like
0Likes
Like

Posted 21 July 2014 - 01:03 PM

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?


Game Engine's WIP Videos - http://www.youtube.com/sicgames88
SIC Games @ GitHub - https://github.com/SICGames?tab=repositories
Simple D2D1 Font Wrapper for D3D11 - https://github.com/SICGames/D2DFontX

#2   Members   

2168
Like
1Likes
Like

Posted 21 July 2014 - 01:10 PM

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, 21 July 2014 - 01:15 PM.

Follow Shogun3D on the official website: http://shogun3d.net

Posted Image Posted Image Posted Image Posted Image

"Yo mama so fat, she can't be frustum culled." - yoshi_lol

"One objection to a “critique of C#” would be that you can’t talk about C# without talking about the whole “.Net experience”. However, one can approach the topic of Hitler without a complete discussion of Nationalist Socialism, so I feel justified." - Steve White.

#3   Members   

805
Like
0Likes
Like

Posted 21 July 2014 - 01:19 PM

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.


Game Engine's WIP Videos - http://www.youtube.com/sicgames88
SIC Games @ GitHub - https://github.com/SICGames?tab=repositories
Simple D2D1 Font Wrapper for D3D11 - https://github.com/SICGames/D2DFontX

#4   Members   

7654
Like
5Likes
Like

Posted 21 July 2014 - 01:45 PM

*
POPULAR


 if gEngine is not allocated, then calling ::Create is just going to crash.

 

Well, the C++ standard might say that it is undefined behavior (I'm not sure), but it shouldn't crash since ::Create (in its current form) doesn't reference any object state. Of course, there's no reason to do it this way, as you pointed out.



#5   GDNet+   

10739
Like
4Likes
Like

Posted 21 July 2014 - 02:00 PM

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();

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.


#6   Members   

805
Like
0Likes
Like

Posted 21 July 2014 - 03:45 PM

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.


Game Engine's WIP Videos - http://www.youtube.com/sicgames88
SIC Games @ GitHub - https://github.com/SICGames?tab=repositories
Simple D2D1 Font Wrapper for D3D11 - https://github.com/SICGames/D2DFontX

#7   Members   

805
Like
0Likes
Like

Posted 21 July 2014 - 03:46 PM

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.


Game Engine's WIP Videos - http://www.youtube.com/sicgames88
SIC Games @ GitHub - https://github.com/SICGames?tab=repositories
Simple D2D1 Font Wrapper for D3D11 - https://github.com/SICGames/D2DFontX

#8   Members   

1339
Like
3Likes
Like

Posted 21 July 2014 - 04:20 PM

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

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


#9   Members   

805
Like
0Likes
Like

Posted 21 July 2014 - 05:14 PM

 

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.


Game Engine's WIP Videos - http://www.youtube.com/sicgames88
SIC Games @ GitHub - https://github.com/SICGames?tab=repositories
Simple D2D1 Font Wrapper for D3D11 - https://github.com/SICGames/D2DFontX

#10   Members   

805
Like
0Likes
Like

Posted 21 July 2014 - 05:17 PM

 

 

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.


Game Engine's WIP Videos - http://www.youtube.com/sicgames88
SIC Games @ GitHub - https://github.com/SICGames?tab=repositories
Simple D2D1 Font Wrapper for D3D11 - https://github.com/SICGames/D2DFontX

#11   Members   

1270
Like
1Likes
Like

Posted 21 July 2014 - 07:44 PM

 

 

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.



#12   Members   

6417
Like
5Likes
Like

Posted 21 July 2014 - 08:16 PM

*
POPULAR

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!



#13   Members   

805
Like
0Likes
Like

Posted 21 July 2014 - 08:51 PM

 

 

 

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!


Game Engine's WIP Videos - http://www.youtube.com/sicgames88
SIC Games @ GitHub - https://github.com/SICGames?tab=repositories
Simple D2D1 Font Wrapper for D3D11 - https://github.com/SICGames/D2DFontX

#14   Members   

805
Like
0Likes
Like

Posted 21 July 2014 - 08:54 PM

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.


Game Engine's WIP Videos - http://www.youtube.com/sicgames88
SIC Games @ GitHub - https://github.com/SICGames?tab=repositories
Simple D2D1 Font Wrapper for D3D11 - https://github.com/SICGames/D2DFontX

#15   Members   

6417
Like
3Likes
Like

Posted 21 July 2014 - 08:55 PM


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!).



#16   Members   

6417
Like
0Likes
Like

Posted 21 July 2014 - 08:58 PM

 

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.



#17   Members   

805
Like
0Likes
Like

Posted 21 July 2014 - 09:17 PM

 


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?  


Game Engine's WIP Videos - http://www.youtube.com/sicgames88
SIC Games @ GitHub - https://github.com/SICGames?tab=repositories
Simple D2D1 Font Wrapper for D3D11 - https://github.com/SICGames/D2DFontX

#18   Members   

805
Like
0Likes
Like

Posted 21 July 2014 - 09:19 PM

I know Jason - I'm still trying to figure out what's simplier for me as framework design.


Game Engine's WIP Videos - http://www.youtube.com/sicgames88
SIC Games @ GitHub - https://github.com/SICGames?tab=repositories
Simple D2D1 Font Wrapper for D3D11 - https://github.com/SICGames/D2DFontX

#19   Members   

2015
Like
1Likes
Like

Posted 22 July 2014 - 06:07 AM

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, 22 July 2014 - 06:07 AM.


#20   Members   

138
Like
-1Likes
Like

Posted 22 July 2014 - 06:29 AM

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;
} 





Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.