views:

296

answers:

2

I'm allocating a block of memory in C# to retrieve information from an unmanaged data buffer:

handle = Marshal.AllocHGlobal(33455);

The maximum size of the information retrieved is 33,455 bytes, but the size of the information may be smaller than that in some cases.

How can I determine how many bytes are actually being used in the allocated block, rather than how many are actually allocated?

+4  A: 

How is the system supposed to know what data is used vs random? It doesn't know anything about the structure of your data. All it knows is how much you allocated. You're not storing bytes in the handle. The handle just refers to a chunk of memory that has been set aside for you.

You could initialize the data to a sentinel value (such as 0xcdcdcdcd which Windows will do in debug mode) and then you can calculate it. Or, if the data is a string, you can call strlen() (or one of the safe string functions). Or you can write some wrapper functions that wrap the APIs you use to write to the memory and keep track of how much data you use.

jeffamaphone
The only problem is that the system I'm retrieving data from can't tell me the size of the data it has written. I can track how my changes, but once the unmanaged system writes some data, it'll mess up my calculations. I guess I'm just SOL, then? :(
David Brown
Pretty much... with an oversized buffer, most sensible APIs will return you the number of *used* bytes. Compare to Stream.Read, etc...
Marc Gravell
Thanks! I guess I'll just dig a little deeper into the API and see if there's a function I'm not seeing somewhere.
David Brown
You can detour the unmanaged API. But yeah, you'll have to do some deeper digging. Though if you know the structure of the data, you may be able to use the sentinel value solution.
jeffamaphone
Just to clarify, with the sentinel value method, I should fill the newly allocated buffer with data that I know will never be written by the API and then determine how many bytes match that value, then: AllocatedSize - NumSentinelValues = UsedBytes. Correct?
David Brown
Or read from the front, skipping data you know is yours, until you hit the sentinel. It really depends on what you know.
jeffamaphone
+1  A: 

According to the documentation on MSDN at

http://msdn.microsoft.com/en-us/library/s69bkh17.aspx

You will either get that memory allocated, or you will get an out of memory exception if the request could not be completed.

Thus, the answer to your question is that you will either: 1) Have 33455 bytes of memory allocated and referenced via 'handle', or... 2) AN out of memory exception will be raised, and you will have zero bytes of memory allocated and referenced via 'handle'.

At this very low level, that is all you know.

You could either store a count at the start of the block to indicate how much you have used, or use sentinel values as has been suggested.

Arafangion
Frankly, I don't appreciate the "Let Me Google That For You" bit. Google was of course the first thing I tried, but my question was not about reading how much was allocated (which I already know), but about how much of that allocated block is actually being *used*.
David Brown
Very well, it was probably quite tactless of me to do that, and you're right - I misread the original question - how much is being _used_.
Arafangion
I reread my question and decided it was probably a little unclear, so I've edited it. Thank you for retracting the LMGTFY link.
David Brown