I really appreciate this community and all the help it has provided towards my programming problems that I've had in the past.
Now unfortunately, I cannot seem to find an answer to this problem which, at first glance, seems like a no brainer. Please note that I am currently using C++ 6.0.
Here is the code that I am trying to convert from C#:
byte[] Data = new byte[0x200000];
uint Length = (uint)Data.Length;
In C++, I declared the new byte array Data as follows:
BYTE Data[0x200000];
DWORD Length = sizeof(Data) / sizeof(DWORD);
When I run my program, I receive stack overflow errors (go figure). I believe this is because the array is so large (2 MB if I'm not mistaken).
Is there any way to implement this size array in C++ 6.0?
Defining array this way makes in on stack which ends in stack overflow. You can create very big arrays on heap by using pointers. For example:
BYTE *Data = new BYTE[0x200000];
Currently, you are allocating a lot of memory on the thread's stack, which will cause stack overflow, as stack space is usually limited to a few megabytes. You can create the array on the heap with new (by the way, you are calculating the array length incorrectly):
DWORD length = 0x200000;
BYTE* Data = new BYTE[length];
You might as well use vector<BYTE> instead of a raw array:
vector<BYTE> Data;
int length = Data.size();
Related
How can I find the length of byte* in c#?
It's pointing to a native byte array in an unmanaged c++ library. I need to convert it to a c# byte[], but in order to do so, I need the length. .Length doesn't work.
byte* ETC = //Stuff from unmanaged c++ DLL;
int ETCLength = ????
You cannot know the length of something just from a pointer; the pointer is just the start. Usually, a pointer and a length are passed together. In the future, this may be improved by Span<T> - or maybe it won't! Time will tell.
You need to already know the length. This could be via an API, or it could be via documentation. There may be a pattern to the data that implies the end (nul terminators, for example, or the length being encoded in the first few bytes), but: that approach is how most buffer attacks start. You should always know the length if you're talking about pointers.
I was playing with stackalloc and it throwsoverflow exception when I wrote below piece of code:-
var test = 0x40000000;
unsafe
{
int* result = stackalloc int[test];
result[0] = 5;
}
and when I make changes in test variable as shown below it throws stack overflow exception.
var test = 0x30000000;
unsafe
{
int* result = stackalloc int[test];
result[0] = 5;
}
what is happening in both scenario??
The runtime tries to calculate how much space is needed to store your array, and the first array is too large for the result to fit in the range of the type used.
The first array needs 0x40000000 * 4 = 0x0100000000 bytes of storage, while the second one needs only 0xc0000000 bytes.
Tweaking the array size and the array type (e.g. long[] or char[]) indicates that whenever the required space for the array goes over 0xffffffff you get the OverflowException; otherwise, the runtime attempts to create the array and crashes.
Based on the above I think it's fairly safe to conclude that the required space is being calculated using a value of type uint in a checked context. If the calculation overflows you unsurprisingly get the OverflowException; otherwise the runtime blows up due to the invalid unsafe operation.
Both arrays are larger than the largest allowed size of a single object in .NET (which is 2GB regardless of the platform), meaning that this would fail even if you didn't try to allocate in on the stack.
In the first case, you need 4 * 0x40000000 bytes (int is 32-bit in .NET), which doesn't even fit inside 32-bits and creates an arithmetic overflow. The second case needs ~3GB but is still way larger than the 2GB limit.
Additionally, since you're trying to allocate on the stack, you need to know that the stack size for a single thread is ~1MB by default, so using stackalloc for anything larger than that will also fail.
For example, this will also throw a StackOverflowException:
unsafe
{
byte* result = stackalloc byte[1024 * 1024];
result[0] = 5;
}
I'm doing an experiment as part of an R & D process. I need to be able to set values in a struct and retrieve and set them as a byte[].
Here's my struct:
[StructLayout(LayoutKind.Explicit, Size = 17)]
unsafe internal struct MyBuffer
{
[FieldOffset(0)]
internal fixed byte Bytes[17];
[FieldOffset(0)]
internal long L1;
[FieldOffset(8)]
internal long L2;
[FieldOffset(16)]
internal byte B;
}
Setting the values will obviously automatically set the byte[]:
MyBuffer test = new MyBuffer();
test.L1 = 100;
test.L2 = 200;
test.B = 150;
Inspecting test in debug mode yields what I expect.
What I need is as follows:
To be able to read the unmanaged fixed byte array as a 17 byte long managed array.
To be able to set the unmanaged fixed byte array from a 17 byte managed array.
NOTES:
If at all possible, I don't want to use marshalling as this is a time sensitive operation.
I can't omit the fixed directive as that throws a runtime error due to the overlapping of objects and non-objects in the struct.
You're already using unsafe code, so why not simply get a pointer to the structure and pass it? Doesn't this work?
MyBuffer bf = new MyBuffer();
bf.L1 = 23;
unsafe
{
MyBuffer* pStruct = &bf;
YourNativeMethod(pStruct);
}
[DllImport]
static extern void YourNativeMethod(MyBuffer* pStruct);
To avoid all marshalling, you might have to write a C++/CLI wrapper, I'm not sure if .NET does marshalling even if you pass an unsafe pointer.
You don't even need the byte-array, the native method certainly doesn't care whether you're passing a pointer to a byte array or a structure. Everything is a byte array :D
EDIT: Since your case doesn't explicitly call a native method, we have to go around this.
The problem is, fixed byte[] isn't actually a byte array at all. It's simply a sequence of 17 bytes, nothing more. That's not enough for a .NET array. So we have to copy it to a new array (it might be worthwhile to keep "buffer" byte arrays ready and recycle them to avoid allocations and deallocations). This can be done either through Marshal.Copy or some unsafe pointer fun:
byte[] bytes = new byte[17];
unsafe
{
IntPtr srcPtr = new IntPtr(bf.Bytes);
{
Marshal.Copy(srcPtr, bytes, 0, 17);
}
}
This uses direct memory copying, but does some checks. In my testing, it's a great way to copy bigger arrays (for me the break-even point was somewhere around 50 bytes). If your array is smaller, the overhead of those checks gets higher compared to total copy time, so you might want to use byte-by-byte copying instead:
byte[] bytes = new byte[17];
unsafe
{
byte* srcPtr = bf.Bytes;
fixed (byte* bPtr = bytes)
{
var j = 0;
while (j++ < 17)
{
*(bPtr + j) = *(srcPtr++);
}
}
}
I hope I don't have to tell you to be careful around this kind of code :)
In any case, I wouldn't worry about the performance too much and I'd use the Marshal.Copy variant, simply because your DB call is going to be the bottle-neck anyway. The safer option is better :)
There's also a few tricks you can use to speed this up, for example copying a whole int or long at a time, which the CPU is much better, although it's trickier. Trying with a simple variant (a length with a multiple of 4, copying a whole int at a time) cut my test runtime by four. If your data length is not a multiple of four, you'd simply copy the remainder as bytes.
I have byte array. I need to drop first 4 bytes, like that:
byte[] newArray = new byte[byteArray.Length - 4];
Buffer.BlockCopy(byteArray, 4, newArray, 0, byteArray.Length - 4);
But can I just move pointer in C/C++ style? :
byte[] byteMsg = byteArray + 4;
I do not want to allocate extra memory until absolutely requried because this code is executed pretty often.
upd: I receive data from Socket so I probably should just use another version of Receive count = s.Receive(byteArray);
No, you can't do that. A .NET array is always of a fixed size, and you can't do pointer arithmetic on it outside unsafe code.
Try using ArraySegment instead
I wouldn't worry, the GC will take care of cleaning up the memory that you're no longer using provided it is not being referenced.
Arrays in C# are immutable. You can't modify them, so if you need to drop the first 4 bytes then you're going to have to reallocate. As thecoop suggests, I'd take a look at ArraySegment and use that to pass around to other functions, if these first 4 bytes are not important to you.
It's also worth noting that yes, in C++, we'd use a bit of pointer arithmetic, but definitely keep hold of the original pointer, less we end up de-allocated and losing 4 bytes to the Demons :)
Just leave the Byte Array untouched and use a MemoryStream and it's offset capability. this won't change your array and you have the ability to skip the first n bytes.
var memoryStream = new MemoryStream(byteArray);
// do whatever you want with the memory stream
To explain: I have array of ints as input. I need to convert it to array of bytes, where 1 int = 4 bytes (big endian). In C++, I can easily just cast it and then access to the field as if it was byte array, without copying or counting the data - just direct access. Is this possible in C#? And in C# 2.0?
Yes, using unsafe code:
int[] arr =...
fixed(int* ptr = arr) {
byte* ptr2 = (byte*)ptr;
// now access ptr2[n]
}
If the compiler complains, add a (void*):
byte* ptr2 = (byte*)(void*)ptr;
You can create a byte[] 4 times the size of your int[] lenght.
Then, you iterate trough your integer array & get the byte array from:
BitConverter.GetBytes(int32);
Next you copy the 4 bytes from this function to the correct offset (i * 4) using Buffer.BlockCopy.
BitConverter
Buffer.BlockCopy
Have a look at the BitConverter class. You could iterate through the array of int, and call BitConverter.GetBytes(Int32) to get a byte[4] for each one.
If you write unsafe code, you can fix the array in memory, get a pointer to its beginning, and cast that pointer.
unsafe
{
fixed(int* pi=arr)
{
byte* pb=(byte*)pi;
...
}
}
An array in .net is prefixed with the number of elements, so you can't safely convert between int[] and byte[] that points to the same data. You can cast between uint[] and int[] (at least as far as .net is concerned, the support for this feature in C# itself is a bit inconsistent).
There is also a union based trick to reinterpret cast references, but I strongly recommend not using it.
The usual way to get individual integers from a byte array in native-endian order is BitConverter, but its relatively slow. Manual code is often faster. And of course it doesn't support the reverse conversion.
One way to manually convert assuming little-endian (managed about 400 million reads per second on my 2.6GHz i3):
byte GetByte(int[] arr, int index)
{
uint elem=(uint)arr[index>>2];
return (byte)(elem>>( (index&3)* 8));
}
I recommend manually writing code that uses bitshifting to access individual bytes if you want to go with managed code, and pointers if you want the last bit of performance.
You also need to be careful about endianness issues. Some of these methods only support native endianness.
The simplest way in type-safe managed code is to use:
byte[] result = new byte[intArray.Length * sizeof(int)];
Buffer.BlockCopy(intArray, 0, result, 0, result.Length);
That doesn't quite do what I think your question asked, since on little endian architectures (like x86 or ARM), the result array will end up being little endian, but I'm pretty sure the same is true for C++ as well.
If you can use unsafe{}, you have other options:
unsafe{
fixed(byte* result = (byte*)(void*)intArray){
// Do stuff with result.
}
}