0

I am writing a managed wrapper for a game engine written in C to challenge myself. I have started to wrap unmanaged pointers in SafeHandle derivatives, but it donned on me that calls to the unmanaged functions that could return the same pointer will probably create new SafeHandles, and if one of them gets disposed, the rest of them will become invalid.

How can I prevent this from happening efficiently? I doubt the marshaller automagically tracks duplicates...

sonicbhoc
  • 434
  • 3
  • 15
  • 2
    How would you solve this problem in unmanaged code? It seems to me that if the library were to do what you claim then it would be unusable. I rather suspect that you are creating a problem where none exists. – David Heffernan Jan 23 '18 at 06:22
  • I'm not sure what you mean. Passing pointers around in C programs is normal, is it not? I'm just trying to make sure that each pointer that I retrieve is associated with one SafeHandle class so I'm not instantiating unique SafeHandle instances that all point to the same unmanaged memory. – sonicbhoc Jan 23 '18 at 15:24

2 Answers2

0

You are trying to tackle the problem which most managed pointers and non garbage collecting techniques try to answer. Depending on the use case, there are multiple solutions to this -

  1. You can use reference counts - You basically maintain a count of number of Handles holding a particular pointer and overload (in C use function calls instead of assignments) operators to update the counts on assignments. You then free the pointer only after the count has reached 0. This approach although accurate has significant overheads and also is susceptible to cycles and hence can leak memory. This is a reference count ownership model.

  2. You can create a unique_ptr. What this basically means that at any time only 1 handle holds the reference to a particular pointer. This means if you do something like -

    a = b 
    

    The pointer will be copied from b to a and b will automatically become invalid (more of a contract of the API, rather than implementation). This means the user has to build the code around these constraints. Here the free is done when any object holding a reference goes out of scope. This is a exclusive ownership model.

There are other approaches too(like weak_ptr) and you can read about them in any C++ reference.

Ajay Brahmakshatriya
  • 8,993
  • 3
  • 26
  • 49
  • I'm trying to handle things on the managed (C#) side though. These sound like what you would do on the unmanaged (C/C++) side. When I marshal calls to C functions using P/Invoke in C#, I marshal `IntPtr`s as `SafeHandle`s, which means the marhsaller wraps the pointer in an object as it is returned automatically. What I'm trying to do is cut down on the number of *duplicate* `SafeHandle` objects being created by the marhsaller. – sonicbhoc Jan 23 '18 at 14:57
-1

Though this answer was to another question, it would work in this case.

I could make a factory class that calls out to managed functions for me, then creates the SafeHandles manually in a Constrained Execution Region, like the marhsaller does. This factory class can keep track of the unmanaged pointers and, if a SafeHandle was already created, return it instead of making a new one.

sonicbhoc
  • 434
  • 3
  • 15