Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Undefined behavior? Marshalling native non-PODs yield different results depending on their size #2357

Closed
Alan-FGR opened this issue Mar 21, 2019 · 4 comments

Comments

@Alan-FGR
Copy link

Hello there.
I was marshaling some data from C++ and I came across a strange inconsistent behavior, here's a repro project:
https://github.com/Alan-FGR/PinvokeDebug
here's the native code:
https://github.com/Alan-FGR/PinvokeDebug/blob/c63b8e1b310ab6ad0316e1044580789aa7348b2f/Dll/Dll.cpp#L9-L44
here's the C# code:
https://github.com/Alan-FGR/PinvokeDebug/blob/c63b8e1b310ab6ad0316e1044580789aa7348b2f/PinvokeProblemDebug/Program.cs#L8-L46
(github should be displaying the lines here, that isn't working on my end though)
Note how the only difference is that single extra float. The version with 3 floats works fine, with 2 it doesn't, but if I cast it into a POD it works fine.
Is marshaling non-PODs undefined behavior or something? I can see why that doesn't work since the destructor is called when exiting the scope, but what I don't understand is the inconsistency there.
I couldn't find anything regarding that behavior. I don't really understand why that varies according to data size and I think that should be at least documented.
Thank you in advance.

@tannergooding
Copy link
Member

This should likely be filed on dotnet/coreclr since it looks like a runtime question rather than a language issue.

@Alan-FGR
Copy link
Author

@tannergooding oh hey there 😃.
While it's very possible I've opened the issue in the wrong repo, I'm not sure tbh... am I even supposed to be able to do that? And what about PODs, can you blit them back reliably?
Before anything I'd like to know if that's proper usage and if that's really not supposed to happen, and that's not implementation imho, but more of a language/usage issue.
Unfortunately documentation and just general information on interoping seems to be very scarce so I couldn't even figure whether that's really a problem or if that's just UB.
As @scalablecory suggested, passing a ref from C# fixes that, but that's not the same thing especially because memory is initialized in the managed side when creating the struct there to pass as ref, what isn't really necessary.

@tannergooding
Copy link
Member

Interop is not a function of the language but a function of the runtime. The runtime team in dotnet/coreclr should be better suited at answering your interop related questions (and it is likely worthwhile to continue the discussion there rather than causing noise here in csharplang).

There are a lot of things that come into play for interop including the target calling convention, what platform you are running against, various attributes, etc. Almost all the documentation for this can be found under: https://docs.microsoft.com/en-us/dotnet/framework/interop/

@Alan-FGR
Copy link
Author

OK. Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants