SteamNetworkingMessage_t crashes on Release() / SteamNetworkingMessage_t usage
See original GitHub issueI am fully aware that there is an issue about this problem here, and I am fully aware that it regards the development of the library rather than the usage, which is what I need. After reading it multiple times I still can’t understand exactly how am I supposed to clear messages, since Release()
method still crashes Unity on version 14.0.0. My code looks like this:
MessageCount = SteamNetworkingSockets.ReceiveMessagesOnPollGroup(PollGroup, PointerBuffer, 32);
for (int i = 0; i < MessageCount; ++i)
{
SteamNetworkingMessage_t NewMessage = Marshal.PtrToStructure<SteamNetworkingMessage_t>(PointerBuffer[i]);
Marshal.Copy(NewMessage.m_pData, Buffer, 0, NewMessage.m_cbSize);
FillSize = NewMessage.m_cbSize;
// Something happens here like parsing/serialization etc
NewMessage.Release();
}
Issue Analytics
- State:
- Created 3 years ago
- Comments:7 (2 by maintainers)
Top Results From Across the Web
Program only crashes as release build -- how to debug?
One technique to at least narrow down the problem is to use MessageBox() to display quick statements stating what part of the program...
Read more >Works fine on DEBUG but crashes when running ...
Any time a MAUI/Xamarin app works fine in debug mode and crashes in release, the first thing to check is the linker and/or...
Read more >Crashes | App quality
An Android app crashes whenever there's an unexpected exit caused by an unhandled exception or signal. An app that is written using Java...
Read more >Android App suddenly crashes when compiling in Release ...
Hi My App was working fine when build to release mode, and both when downloading from Google play store or from a Android...
Read more >Troubleshoot crash or freeze in Photoshop
Unable to open Photoshop? Photoshop crashes or freezes on launch? We're here to help! Fix common crash issues in 6 simple steps.
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
@rlabrecque So, as you’ve correctly identified, the crash is the direct consequence of the fact that the wrong pointer is being passed to the native function.
SteamAPI_SteamNetworkingMessage_t_Release(IntPtr self)
expects the argument to be a pointer tothis
,&message
(it is an instance method in C++). Instead, the current implementation ofSteamNetworkingMessage_t.Release
passesm_pfnFreeData
, which is presumably a copy-paste bug as I’ve found at least one other library doing it.m_pfnFreeData
is actually meant for the reverse scenario: you would construct a message with a custom allocator (say, GC,new
and pinnedGCHandle
in C#) and assign this field to a custom deallocator function (something likeGCHandle.Release
for that managed array), then pass that message back to native which would take care of calling that deallocation function as appropriate.The fix might be as simple as just doing something like this in
Release
:However, it is not 100% bulletproof as the native side may be expecting the exact same pointer that it passed to you via, e. g.,
ReceiveMessagesOnPollGroup
or similar methods (full disclosure: I am commenting here after helping @AG4W figure this out, so I am not familiar with the library or the Steam API). You also cannot exactly “carry” this pointer inSteamNetworkingMessage_t
, as it must be field-for-field compatible with the native version, as your users usingMarshal.PtrToStructure
are already relying on this (you might be able to play tricks with appending fields to the back or assigning the pointer tom_pfnFreeData
, but I would not recommend this approach due its questionable reliability and maintainability characteristics). In my opinion, your best course of action to unblock users right now would be to:SteamNetworkingMessage_t.Release
and point users to the new API in the obsoletion message.SteamNetworkingMessage_t.Release
via the use of[EditorBrowsable(EditorBrowsableState.Never)]
attribute (optional, might not be worth it).Going on a bit of a tangent here: the library seems to provide a managed wrapper over the Steam API, but it appears to be inconsistent it its design. In places, it exposes very low-level
C
-like primitives, as is the case here, where users have to manually deduce that they need to treatIntPtr
s asSteamNetworkingMessage_t*
and dereference them accordingly, while at the same time hiding the raw imports. You might consider either exposing the raw imports (preferably with blittable signatures instead of using expensive marshalling features like arrays with[Out, In]
attributes) so that users who are already operating on that low level can consume them while not dealing with the complexities of packaging, platform and bitness differences, and/or exposing a higher level API that would useSafeHandle
s and such for messages, friendly names and signatures, etc.I think what we may want to be doing here is:
That’s what they do over here: https://github.com/nxrighthere/ValveSockets-CSharp/blob/656d236e381cb9b0c20c12795f1c9907e25cc62a/ValveSockets.cs#L648
One thing we could possibly do relatively easy is have a constructor that takes an IntPtr, and handles this stuff like so:
We possibly want to make SteamNetworkingMessage_t IDisposable too?
I haven’t written “client” code using these myself yet, so let me know what you would like and we can make that happen. 👍
The ValveSockets-CSharp library does some clever performance stuff with pooling, and I’d like that to continue to be possible with Steamworks.NET as well.