我正在使用CDB(Microsoft控制台调试器)和WinDbg尝试在P/Invoke发生堆损坏时将其强制破坏到ReadFile中。我从文本文件中读取的字节比分配给chBuf数组的字节多。调试器直到GC.Collect
之后才看到访问冲突,这对我来说太晚了。在运行程序之前,我先运行
gflags -p /enable testheap.exe /unaligned
效果似乎没用。我写了这个小测试程序,将发现的内容应用于调试具有堆损坏问题的大型商业程序。
我还尝试了使用Application Verifier和MDA callbackOnCollectedDelegate进行DebugDiag的操作,但没有成功。我对
gflags
的使用不是应该在ReadFile之后立即检测堆损坏吗?代码:
namespace TestHeap
public partial class Form1 : Form
{
[DllImport("kernel32.dll", SetLastError = true)]
static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess,
uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition,
uint dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool ReadFile(SafeFileHandle hFile, [Out] byte[] lpBuffer,
uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, IntPtr lpOverlapped);
string fileName = "testHeap.txt";
const uint GENERIC_READ = 0x80000000;
const uint OPEN_EXISTING = 3;
SafeFileHandle sh;
byte[] chBuf = new byte[8];
public Form1()
{
InitializeComponent();
}
private void testBtn_Click(object sender, EventArgs e)
{
bool nStat;
uint bytesToRead = 1025;
uint bytesRead = 0;
if (!(nStat = ReadFile( sh, chBuf, bytesToRead, out bytesRead, IntPtr.Zero)))
Debug.Print("testBtn_Click error in ReadFile, nStat = {0}", nStat);
MessageBox.Show(string.Format("After ReadFile, bytesToRead = {0},\n bytes read = {1}", bytesToRead, bytesRead));
GC.Collect();
MessageBox.Show("testBtn_Click end, after GC.Collect");
}
private void Form1_Load(object sender, EventArgs e)
{
sh = CreateFile(fileName, GENERIC_READ, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
}
}
}
最佳答案
只是一个猜测,但我相信意外的gflags行为是由以下行引起的:byte[] chBuf = new byte[8];
由于chBuf
由CLR管理,因此gflags无法将填充模式放在其后以检测缓冲区溢出。尝试将其更改为:IntPtr chBuf = Marshal.AllocHGlobal(8);
这样您就可以在非托管堆中进行分配。 Gflags应该能够使用它。另外,您可能需要更改ReadFile
的签名才能起作用:
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool ReadFile(SafeFileHandle hFile, [Out] IntPtr lpBuffer,
uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, IntPtr lpOverlapped);
关于c# - 在垃圾收集之前检测堆损坏,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7948932/