【问题标题】:Why does my Interop code throw a "Stack cookie instrumentation code detected a stack-based buffer overrun" exception?为什么我的互操作代码会引发“堆栈 cookie 检测代码检测到基于堆栈的缓冲区溢出”异常?
【发布时间】:2015-08-05 12:10:30
【问题描述】:

因为我在内存读取等方面有点搞砸了。我制作了包含 1000000 个元素的 byte[] 数组,这样它们每个可以存储 1MB 的数据。我最终使用了这 1000000 个元素数组中的大约 750-isch,当我检索数据时,我一一添加,例如:获取 MB 内存,添加到列表,获取下一个 MB。但它只是因溢出异常而失败。那么 List 可以包含多少元素是否存在实际限制,或者 List 是否存在“数据”限制?如果我没有超过这个限制,是什么导致了这个问题的发生?

编辑:异常截图

EDIT2:我正在从一个 c++ dll 调用一个函数,该函数读取下一个 1MB 并返回一个指向该数组的指针

编辑3: C#部分

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

包装器

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

c++部分 .cpp 文件
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 文件

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

EDIT4:感谢所有的见解和快速响应的家伙(和女孩,如果他们在那里:S)

EDIT5:现在全部修复,程序正在滚动

【问题讨论】:

  • 你能发布一些代码和确切的异常类型吗?
  • List<byte[]> 对象不会是这里的问题——它将是您为所有单独的字节数组分配的内存。是的,如果你的内存用完了,你最终会得到一个异常......
  • 你到底在做什么?这不是您应该在托管代码中看到的那种异常。你在使用不安全的代码吗?还是 P/Invokes?
  • 该异常不是由于内存不足问题,而是由于堆栈损坏问题。你在调用非托管代码吗?
  • 不,托管端没有限制。你可能正在做一些非常不安全的事情,最终你会覆盖你不应该做的事情。也许您在调用 C++ 函数时使用了错误的调用约定,或者您正在传递未修复的指针,或者您期望调用正在传递对您的 byte[] 的引用(它不是 - 它复制了数组结束) - 调用本机代码绝非易事。是否在 C# 和 C++ 中添加代码和分配函数的定义?

标签: c# c++ arrays memory limit


【解决方案1】:

好的,代码很明显了。

您在 C++ 端分配一个本地数组,并返回一个指向该数组的指针。如果您习惯使用本机代码,那应该已经敲响了警钟——您不会返回指向本地代码的指针!

然后你不正确地使用Marshal.Copy 来杀死它 - 而不是从你从 C++ 代码中获得的数据中复制(这可能是格式错误的,因为你正在返回一个指向本地的指针......),你复制将 C# 字节数组转移到您从 C++ 函数获得的指针 - 覆盖 C++ 堆栈。轰隆隆。

但是,我不明白您为什么要使用 C++ 库来调用 ReadProcessMemory - 为什么不直接调用它呢?我在https://github.com/Luaancz/AutoPoke 的小工具中就是这样做的。

【讨论】:

  • 好的,感谢您澄清导致此错误的原因
  • @Freenode-newbostonSebivor 我在 Hyun 发布代码之前就已经写好了答案,我只是等着确定:D 这似乎是一个太明显的错误......
  • return 甚至没有那么令人震惊...如果您想震惊,请查看 Address 正在做什么!
  • 因为我正在练习制作可以互操作的代码
  • @HyunMi 这是一个很好的做法——但请确保您首先了解本机代码的复杂性。有很多。在现实世界中,调用者将分配缓冲区,这更加灵活和安全(不要忘记 - 没有自动内存管理来清理非托管代码中的混乱;这就是它被称为非托管的原因)。您可以在我提供的代码中看到 C# 方面 - 一个简单的 [Out] byte[] 是您在 P/Invoke 上所需要的,而编组器将负责其余的工作。
【解决方案2】:

是的,但它取决于你有多少内存。

如果您有足够的内存来添加 Int32.MaxValue 值,这会破坏 List<T> 类。

这可能是OverflowException 的原因。

如果您的内存不足,我希望收到 OutOfMemoryException


您得到的错误不是 C# 异常,而是 C++ 异常,investigated in this question

要么你在 C++ 代码中做错了什么,要么你在 C# 中错误地调用了它。请注意,这与我认为我已经回答的原始问题非常不同。

【讨论】:

  • 那不提供解释,750*1MB = 750MB,每个数组有 1000000 个元素 750MB
  • @HyunMi 要么你破坏了 CLR,要么你做了一些不受管理的事情。
猜你喜欢
  • 2017-03-30
  • 1970-01-01
  • 1970-01-01
  • 2015-12-31
  • 2011-12-11
  • 2011-10-26
  • 2017-02-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多