void test1()
{
LPBYTE pData = new BYTE[Buflen];
test2(pData);
}
void test2(LPBYTE pData)
{
}
问题1:如何在test2函数得到pData指向的内存区长度?test2的参数列表不能变,意思你只有LPBYTE pData。
问题2:如果上面问题你知道那请告诉我,下面的问题不用看了。
问题3:在test2()中调用delete[] pData;是能够正确删除pData指向的内存区的,这说明delete关键字是能够知道pData的长度的,那请问为什么C++没有提供能够直接通过LPBYTE指针得到内存区长度的方法?
直接察看内存,可以看到new分配的内存在结束的尾部有连续的4个"FD FD FD FD",当然这个只对new操作符有效。如果你用其他的分配方式,就不一定存在这个结束符。因此在设计函数的时候,如果你自己不能够给出正确的长度,而是依赖内存本身的结束,那么就有如下的缺陷。
首先
pMem = new BYTE[BUF_LEN];
delete [] pMem
这是正确的,但是delete [] (pMem+1)仍然是可以执行的。
这样子就带来的不正确的内存释放。
另外,指针本身只是个变量,意味着随时可以被赋值改变,如果函数只传递了指针而不指明这个指针指向的内存大小,那么在使用上存在很大的缺陷,这也是早期的Windows系统为什么有那么多著名的溢出漏洞的原因。
从设计风格上来说,函数外部申请分配的内存在一个函数内部释放本身也是不合理的设计。意味着函数需要知道内存管理的细节,也就是必须new-delete,malloc-free, HeapAlloc-HeapFree, VirtualAlloc-VirtualFree, GlobalAlloc-GlobalFree这样的配对设计细节。
因此,对你的问题:
问题1:如何在test2函数得到pData指向的内存区长度?test2的参数列表不能变,意思你只有LPBYTE pData。
在不知道指针的分配细节的情况下,答案是不能得到。
N/A
问题3:在test2()中调用delete[] pData;是能够正确删除pData指向的内存区的,这说明delete关键字是能够知道pData的长度的,那请问为什么C++没有提供能够直接通过LPBYTE指针得到内存区长度的方法?
实际上,你使用free或者HeapFree、GlobalFree这样的函数在代码中编译也一样可以通过,但是运行期显然会遇到错误。你的代码是因为都源于你自己的设计,你自己心里知道那个pData是通过new申请分配的数组,因此也就想当然地认为delete [] pData正确。按照封装和减少耦合的设计原则,这种做法属于不良的设计。
因为这样做意味着,你的test2函数传递的指针必须通过new得来,而且经过这个test2之后,指针不可以再用这条默认规则的存在。也就是说,你的test2函数是不适合重用的,存在着设计缺陷。