Windows内核驱动中使用new和delete

在Windows驱动中如果要分配内存,我们使用的ExAllocatePoolWithTag,ExAllocatePool,而释放内存时使用的是ExAllocatePoolWithTag和ExFreePool函数。
详情的使用可详见:Windows内核驱动 一节。

我们知道,在内核中其实不是不能用C++,而是使用时有很大的限制。如果稍不留神,就会掉进坑里,这时问题其实是很难查的,所以一般情况下我们直接使用C语言编程。但随着驱动的复杂和微软为了加速音视频等,应用层的接口全部换成了COM接口,这样直接导致了驱动就必须直接使用C++来编程。

使用C++编程,首先要解决的一个问题就是内存的分配与释放,这时就必须解决的是new和delete运算符的重载。

这里我们提供一段示例代码,分别实现了new new[],delete,delete[]的重载。


#pragma code_seg("PAGE")

//
// New and delete operators
//
_When_((PoolType & NonPagedPoolMustSucceed) != 0,
    __drv_reportError("Must succeed pool allocations are forbidden. "
            "Allocation failures cause a system crash"))
void* __cdecl operator new(size_t Size, POOL_TYPE PoolType)
{
    PAGED_CODE();

    Size = (Size != 0) ? Size : 1;

    void* pObject = ExAllocatePoolWithTag(PoolType, Size, BDDTAG);

#if DBG
    if (pObject != NULL)
    {
        RtlFillMemory(pObject, Size, 0xCD);
    }
#endif // DBG

    return pObject;
}

_When_((PoolType & NonPagedPoolMustSucceed) != 0,
    __drv_reportError("Must succeed pool allocations are forbidden. "
            "Allocation failures cause a system crash"))
void* __cdecl operator new[](size_t Size, POOL_TYPE PoolType)
{
    PAGED_CODE();

    Size = (Size != 0) ? Size : 1;

    void* pObject = ExAllocatePoolWithTag(PoolType, Size, BDDTAG);

#if DBG
    if (pObject != NULL)
    {
        RtlFillMemory(pObject, Size, 0xCD);
    }
#endif // DBG

    return pObject;
}

void __cdecl operator delete(void* pObject)
{
    PAGED_CODE();

    if (pObject != NULL)
    {
        ExFreePool(pObject);
    }
}

void __cdecl operator delete[](void* pObject)
{
    PAGED_CODE();

    if (pObject != NULL)
    {
        ExFreePool(pObject);
    }
}

其实从代码来看,new和delete运算符的重载只是对ExAllocatePoolWithTag和ExFreePool函数的包装,其本质还是调用的是Windows内核提供的内存分配和释放函数。

new使用示例:

BASIC_DISPLAY_DRIVER* pBDD = new(NonPagedPoolNx) BASIC_DISPLAY_DRIVER(pPhysicalDeviceObject);
if (pBDD == NULL)
{
    BDD_LOG_LOW_RESOURCE0("pBDD failed to be allocated");
    return STATUS_NO_MEMORY;
}

delete使用示例:

BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
if (pBDD)
{
   delete pBDD;
   pBDD = NULL;
}

调式模式下堆内存的0xcdcdcdcd

这里说明一下,在dbg模式下,将分配的内存全部置为0xcd,这和应用层在调试模式下堆的内存初始化为致。
0xcd其实这里是int指令的指令,再配合一个cd,就变成了int cd,说明直接行的是中断0xcd,这样CPU执行到此处就会出现中断异常。这和栈上的0xcc,int3的原理一致。
这里附一段相关反汇编指令代码:

00CC0100 CC                   int         3  
00CC0101 CD 05                int         5  
00CC0103 CD CD                int         0CDh  
00CC0105 CD CD                int         0CDh
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

Powered by bytekits.com,汇天下文字,成非凡梦想!!!