Обнаружить повреждение кучи ДО сбора мусора - PullRequest
3 голосов
/ 31 октября 2011

Я использую CDB (Microsoft Console Debugger,) и WinDbg , чтобы попытаться форсировать разрыв, когда P / Invoke в ReadFile происходит повреждение кучи.Я прочитал намного больше байтов из текстового файла, чем то, что я выделил массиву chBuf.Отладчик не видит нарушения доступа до тех пор, пока GC.Collect, что для меня слишком поздно .До запуска моей программы я запускаю

gflags -p /enable testheap.exe /unaligned

Эффект кажется бесполезным.Я написал эту небольшую тестовую программу, чтобы применить то, что я нашел, к отладке гораздо более крупной коммерческой программы с проблемами повреждения кучи.

Я также безуспешно пробовал DebugDiag с Application Verifier и MDA callbackOnCollectedDelegate,Разве мое использование 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);
        }
    }
}

1 Ответ

1 голос
/ 31 октября 2011

Просто предположение, но я полагаю, что неожиданное поведение 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);
...