3

Since I was messing a bit around with memory reading etc etc. And I made byte[] arrays with 1000000 elements so that they would store 1MB of data each. I wound up using around 750-isch of these 1000000 element array, which I added one by one when I retrieved data, eg: get MB of memory, add to list, get next MB. But it just failed with an overflow exception. So is there an actual limit of how much elements a List can contain, or is there a "data" limit to the List? If I didn't cross this limit what could have caused this problem to occur?

EDIT: Screenshot of exception enter image description here

EDIT2: I am calling a function from a c++ dll that reads the next 1MB and returns a pointer to that array

EDIT3: C# part

private static void FetchNextBuffer()
{
    IntPtr pRaw = Wrapper.GetNextMB();
    byte[] buff = new byte[1000000];
    Marshal.Copy(buff, 0, pRaw, 1000000);
    RawDataFetch.Add(buff);
}

wrapper

[DllImport("Dumper.dll")]
public static extern IntPtr GetNextMB();

c++ part .cpp file
extern byte * __cdecl GetNextMB()
{
    if (!VarsSet) SetVars();
    byte buffer[1000000];
    ReadProcessMemory(pHandle, (void*)Address, &buffer, sizeof(buffer), 0);
    Address = Address + sizeof(buffer);
    return buffer;
}

.h file

extern "C"
{
    __declspec(dllexport) DWORD __cdecl GetPID();
    __declspec(dllexport)  byte * __cdecl GetNextMB();
}

EDIT4: Thank you for all the insights and quick response guys (and girls if they are out there :S)

EDIT5: all fixed now and program is rolling

funie200
  • 3,688
  • 5
  • 21
  • 34
  • 3
    Could you post some code and the exact exception type? – NeddySpaghetti Aug 05 '15 at 12:13
  • 1
    The `List` object won't be the problem here - it'll be the memory you're allocating for all the separate byte arrays. And yes, if you run out of memory, you'll eventually get an exception... – Jon Skeet Aug 05 '15 at 12:14
  • sure just give me a second –  Aug 05 '15 at 12:14
  • Where's you code for us to look at? Keep in mind that for a 32bit application, the process is limited to 2GB and for a 64bit application the limit is 1TB. – Shar1er80 Aug 05 '15 at 12:15
  • StackOverflowException? I'd check **also** something else, not out of memory problems – Adriano Repetti Aug 05 '15 at 12:15
  • @Shar1er80 that would not explain the exception, 750*1MB = 750 MB that is still in bound for a 32-bit application –  Aug 05 '15 at 12:18
  • Personally I dont think it is because I do not have enough memory, wouldn't that give me an OutOfMemoryException? –  Aug 05 '15 at 12:19
  • 1
    What are you doing exactly? That's not the kind of exception you should ever see in managed code. Are you using unsafe code? Or P/Invokes? – Luaan Aug 05 '15 at 12:20
  • 3
    That exception is not due to out of memory problems, it is because of a stack corruption problem. Are you calling unmanaged code? – Lasse V. Karlsen Aug 05 '15 at 12:22
  • @Luaan I am using a c++ dll to read the 1MB memory chunks, this dll return me a pointer towards the byte[] array holding the buffer, which worked fine since I verified it manually, everything in my program is working fine up to a certain point where there is to much data which led me to believe I hit some sort of limit –  Aug 05 '15 at 12:22
  • Do you get any more info when checking the "break" checkbox? Are you calling the DLL from multiple threads? Can you post the exact P/Invoke code? – Dax Fohl Aug 05 '15 at 12:27
  • 1
    Nope, no limit on the managed side. You're probably doing something horribly unsafe and eventually you overwrite something you shouldn't. Perhaps you're using the wrong calling conventions when calling the C++ function or you're passing pointers that aren't fixed, or you're expecting that the call is passing a reference to your `byte[]` (it's not - it copies the array over) - calling native code is anything but easy. Care to add your code and the definition of the allocation function in both C# and C++? – Luaan Aug 05 '15 at 12:28
  • Can you provide a runnable piece of code that recreates the problem? – Jodrell Aug 05 '15 at 12:35

2 Answers2

4

Okay, the code makes it obvious.

You allocate a local array on the C++ side, and return a pointer to that. That should already ring alarm bells if you're used to working with native code - you don't return pointers to locals!

And then you kill it with using Marshal.Copy improperly - instead of copying from the data you get from the C++ code (which is possibly malformed, because you're returning a pointer to a local...), you copy the C# byte array over to the pointer you got from the C++ function - overwriting the C++ stack. Boom.

However, I don't see why you'd use a C++ library just to call ReadProcessMemory - why not just invoke that directly? I'm doing just that in my little tool at https://github.com/Luaancz/AutoPoke.

Luaan
  • 62,244
  • 7
  • 97
  • 116
  • O okay, thank you for clarifying what caused this error –  Aug 05 '15 at 12:37
  • @Freenode-newbostonSebivor I had the answer written before Hyun posted the code, I just waited to be sure :D It just seemed like too obvious a mistake... – Luaan Aug 05 '15 at 12:38
  • 1
    The `return` isn't even that shocking... If you want shock, look at what's being done with `Address`! – autistic Aug 05 '15 at 12:40
  • Because I am practicing making code that can interop –  Aug 05 '15 at 12:41
  • @HyunMi That's good practice - but make sure you understand the complexities of native code first. There's *many*. In the real world, the caller would allocate the buffer, which is much more flexible and much safer (don't forget - there's no automatic memory management to clean up the mess in unmanaged code; that's why it's called unmanaged). You can see the C# side of this in the code I provided - a simple `[Out] byte[]` is all you need on the P/Invoke, and the marshaller will take care of the rest. – Luaan Aug 05 '15 at 12:44
  • @HyunMi It really pays to *understand* what you're doing, because most bad things you do will really look like working fine, except for that one strange edge scenario, or except for what happens after running the code for an hour straight, or except... It's very easy to make mistakes that are incredibly hard to reproduce and find and tricky to fix. Always treat any managed/unmanaged interface as a great opportunity for subtle (or not so subtle) errors. – Luaan Aug 05 '15 at 12:46
  • @Luaan Guess I got lucky I went on a rampage and used 750 1000000 elem arrays xD –  Aug 05 '15 at 12:56
1

Yes, but its defined by how much memory you have.

If you have enough memory to have add over Int32.MaxValue values that that would break the List<T> class.

This may the cause of an OverflowException.

If you are running out of memory I'd expect an OutOfMemoryException.


The error you getting is not a C# exception but rather a C++ Exception, investigated in this question.

Either you've done something wrong in your C++ code or you've called it incorrectly from C#. Note, this is very different from the original question that I think I've answered.

Community
  • 1
  • 1
Jodrell
  • 34,946
  • 5
  • 87
  • 124
  • That does not provide an explanation, 750*1MB = 750MB, each array has 1000000 elements 750MB < 16GB max RAM I have (yes it is 64-bit application) 1000000 < int32_max –  Aug 05 '15 at 12:25
  • @HyunMi either you've broken the CLR or you've done something unmanaged. – Jodrell Aug 05 '15 at 12:34