前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++判断char*的指向

C++判断char*的指向

作者头像
magicsoar
发布2018-02-06 10:53:10
1.1K0
发布2018-02-06 10:53:10
举报
文章被收录于专栏:magicsoarmagicsoar
代码语言:javascript
复制
char *a = "Peter";
char b[] = "Peter";
char *c = new char[6];
strcpy_s(c, 6, "Peter");

这里a指向常量区

b指向栈区

c指向堆区

如果我们有这样一个函数

代码语言:javascript
复制
void show(char *temp)
{
//
//
//
}

我们如何判断根据过来的temp的将这些区分出来呢?

1.我们可以首先将指向常量区的a区分出来

因为它所指向的地方是不可以修改的

判断是否可以修改

a.使用函数IsBadReadPtr

函数原型如下

代码语言:javascript
复制
BOOL WINAPI IsBadWritePtr(
  _In_  LPVOID lp,
  _In_  UINT_PTR ucb
);

lp:第一个字节的内存块的指针。

ucb:指定的大小,单位为字节的内存块。如果此参数为零,则返回值为零。

MSDN上部分的解释如下

http://msdn.microsoft.com/en-us/library/windows/desktop/aa366716(v=vs.85).aspx

Verifies that the calling process has write access to the specified range of memory.

Important  This function is obsolete and should not be used. Despite its name, it does not guarantee that the pointer is valid or that the memory pointed to is safe to use. For more information, see Remarks on this page.

翻译(自己翻译的):

验证调用的进程是否可以写入指定范围的内存

主要的:这个函数是废弃的,不应该被使用,不管它的名字,它不保证这个指向内存中的指针是合法的和这段内存是可以安全使用的,对于更多的信息,可以查看这页的评论

示例:

代码语言:javascript
复制
bool  isConst(void* pAddress, DWORD dwSize)
{
    if (IsBadWritePtr(pAddress, dwSize))
        return true;
    return false;
}

int main()
{
    char *a = "Peter";
    char b[] = "Peter";
    char *c = new char[6];
    strcpy_s(c, 6, "Peter");
    cout << isConst(a,strlen(a))<< endl;
    cout << isConst(b, strlen(a)) << endl;
    cout << isConst(c, strlen(a)) << endl;

    system("pause");
}

结果

image
image

b.使用VirtualQuery

函数原型如下

代码语言:javascript
复制
SIZE_T WINAPI VirtualQuery(
  _In_opt_  LPCVOID lpAddress,
  _Out_     PMEMORY_BASIC_INFORMATION lpBuffer,
  _In_      SIZE_T dwLength
);

lpAddress:查询内存的地址。

lpBuffer:指向MEMORY_BASIC_INFORMATION结构的指针,用于接收内存信息。

dwLength:MEMORY_BASIC_INFORMATION结构的大小。

MSDN上部分的解释如下

http://msdn.microsoft.com/en-us/library/windows/desktop/aa366902(v=vs.85).aspx

Retrieves information about a range of pages in the virtual address space of the calling process.

检索对于调用进程的虚拟内存中的页的信息

用于接收的内存信息的MEMORY_BASIC_INFORMATION结构体定义如下

代码语言:javascript
复制
typedef struct _MEMORY_BASIC_INFORMATION {
  PVOID  BaseAddress;
  PVOID  AllocationBase;
  DWORD  AllocationProtect;
  SIZE_T RegionSize;
  DWORD  State;
  DWORD  Protect;
  DWORD  Type;
} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;

BaseAddress:保留区域的基地址 AllocationBase:分配的基地址

AllocationProtect:初次保留时所设置的保护属性 RegionSize:区域大小 State:状态(提交、保留或空闲) Protect: 当前访问保护属性 Type:页面类型

详细请见MSDN

http://msdn.microsoft.com/en-us/library/windows/desktop/aa366775(v=vs.85).aspx

示例

代码语言:javascript
复制
bool  isConst(void* pAddress)
{
    _MEMORY_BASIC_INFORMATION mi = { 0 };
    VirtualQuery(pAddress, &mi, sizeof(mi));
    if (mi.Protect == PAGE_READONLY)
    {
        return true;
    }
    return false;
}

int main()
{
    char *a = "Peter";
    char b[] = "Peter";
    char *c = new char[6];
    strcpy_s(c, 6, "Peter");
    cout << isConst(a)<< endl;
    cout << isConst(b) << endl;
    cout << isConst(c) << endl;
    
    system("pause");
}

结果

image
image

判断是否位于栈上

参考了http://www.cppblog.com/weiym/archive/2012/05/12/174634.html

我们可以在函数内建一个位于栈的对象,然后获得栈空间的初始地址,以及栈的最末尾的地址,就可以判断一个东西是不是为与栈上了

VirtualQuery中用于接收内存信息_MEMORY_BASIC_INFORMATION结构体中有如下成员

BaseAddress:保留区域的基地址 RegionSize:区域大小

代码示例

代码语言:javascript
复制
bool IsObjectOnStack(void* pObject)
{
    int nStackValue(0);

    MEMORY_BASIC_INFORMATION mi = { 0 };
    DWORD dwRet = VirtualQuery(&nStackValue, &mi, sizeof(mi));
    if (dwRet > 0)
    {
        return pObject >= mi.BaseAddress
            && (DWORD)pObject < (DWORD)mi.BaseAddress + mi.RegionSize;
    }

    return FALSE;
}

int main()
{
    char *a = "Peter";
    char b[] = "Peter";
    char *c = new char[6];
    strcpy_s(c, 6, "Peter");
    cout << IsObjectOnStack(a) << endl;
    cout << IsObjectOnStack(b) << endl;
    cout << IsObjectOnStack(c) << endl;
    
    system("pause");
}

运行结果

image
image

解释:nStackValue是一个位于栈上的对象

我们针对它使用 VirtualQuery获得相关的内存信息mi

mi.BaseAddress是栈的初始地址

(DWORD)mi.BaseAddress + mi.RegionSize是栈的最末尾的地址

我们只要判断地址是不是在这二者之间,就可以判断是不是位于栈上了

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档