char *a = "Peter";
char b[] = "Peter";
char *c = new char[];
strcpy_s(c, , "Peter");

这里a指向常量区

b指向栈区

c指向堆区

如果我们有这样一个函数

void show(char *temp)
{
//
//
//
}

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

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

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

判断是否可以修改

a.使用函数IsBadReadPtr

函数原型如下

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.

翻译(自己翻译的):

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

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

示例:

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[];
strcpy_s(c, , "Peter");
cout << isConst(a,strlen(a))<< endl;
cout << isConst(b, strlen(a)) << endl;
cout << isConst(c, strlen(a)) << endl; system("pause");
}

结果

b.使用VirtualQuery

函数原型如下

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结构体定义如下

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
 
示例
bool  isConst(void* pAddress)
{
_MEMORY_BASIC_INFORMATION mi = { };
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[];
strcpy_s(c, , "Peter");
cout << isConst(a)<< endl;
cout << isConst(b) << endl;
cout << isConst(c) << endl; system("pause");
}

结果

判断是否位于栈上

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

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

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

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

代码示例

bool IsObjectOnStack(void* pObject)
{
int nStackValue(); MEMORY_BASIC_INFORMATION mi = { };
DWORD dwRet = VirtualQuery(&nStackValue, &mi, sizeof(mi));
if (dwRet > )
{
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[];
strcpy_s(c, , "Peter");
cout << IsObjectOnStack(a) << endl;
cout << IsObjectOnStack(b) << endl;
cout << IsObjectOnStack(c) << endl; system("pause");
}

运行结果

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

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

mi.BaseAddress是栈的初始地址

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

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

C++判断char*的指向的更多相关文章

  1. Java 中判断char 是否为空格 和空

    //判断是否char是否为空import java.util.*; public class test{ public static void main(String[] args){ String ...

  2. JAVA中判断char是否是中文的几种方法

    1.方法一 char c = 'a'; if((c >= 0x4e00)&&(c <= 0x9fbb)) { System.out.println("是中文&qu ...

  3. 你好,C++(15)四两拨千斤——3.9 指向内存位置的指针

    3.9  指向内存位置的指针 一天,两个变量在街上遇到了: “老兄,你家住哪儿啊?改天找你玩儿去.” “哦,我家在静态存储区的0x0049A024号,你家呢?” “我家在动态存储区的0x0022FF0 ...

  4. JS 判断数据类型的三种方法

    说到数据类型,我们先理一下JavaScript中常见的几种数据类型: 基本类型:string,number,boolean 特殊类型:undefined,null 引用类型:Object,Functi ...

  5. C语言中 指向函数的指针 简介

    引子:在学习CPrimerPlus的第十四章的14.13节中,遇到了如下三行文字,是有关指向函数的指针的,把我搞晕了. char * fump(); //返回指向char的指针的函数 char (* ...

  6. 彻底搞定char/wchar_t/unicode

    彻底搞定char/wchar_t!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! (2013-07-17 10:18:28) 转载▼     从char/wchar_t到TCHAR(1) ...

  7. char类型输出地址

    问题描述: 当输出char的地址时,发现输出的是一个字符: char ch = 'a'; cout<<&ch<<endl;//a @ 因为cout得到一个char类型的 ...

  8. NDK(14)Native的char*和Java的String相互转换

    转自: http://www.cnblogs.com/canphp/archive/2012/11/13/2768937.html 首先确保C/C++源文件的字符编码是UTF-8与JAVA的class ...

  9. char指针

    1.在C语言中,没有字符串类型,因此使用char指针表示字符串. 2.那么问题来了,使用char* 表示字符串,到哪里是结尾呢?因此需要一个特殊的字符作为哨兵,类似迭代器中的end(),这个哨兵就是' ...

随机推荐

  1. c++ 变量共享内存-联合(union)

    共享内存极少使用,所以这里我们仅作了解. .将几个变量放在相同的内存区,但其中只有一个变量在给定时刻有有效值. .程序处理许多不同类型的数据,但是一次只处理一种.要处理的类型在执行期间才能确定. .在 ...

  2. 二维码Aztec简介及其解码实现(zxing-cpp)

    Aztec Code是1995年,由Hand HeldProducts公司的Dr. Andrew Longacre设计.它是一种高容量的二维条形码格式.它可以对ASCII和扩展ASCII码进行编码.当 ...

  3. 1 nodejs

      重点 :  

  4. springboot之assembly的文件配置

    一.在使用springboot框架的时候,存在一个问题.就是我们配置yaml文件,需要单独提出来做参数修改.当然这个是可以通过spring.profiles.active的方式来配置dev,prod等 ...

  5. #2009. 「SCOI2015」小凸玩密室

    神仙题啊.完全想不出 首先看方案.可以从任意一个点开始,在这个点要先走完子树,然后走到父亲,再走兄弟,再走父亲的父亲,父亲的兄弟..一直走到1,1的另外一个子树,结束. 完全不会鸭.jpg 设f[i] ...

  6. H5拖拽 构造拖拽及缩放 pdf文件转换为html预览

    前言: 协助项目需要实现一个签名的功能. 功能说明:1.有文本签名和头像签名.2.头像签名需要实现可拖拽功能.3.需要展示的是pdf的文件并需要获取签名位于pdf文件的相对位置. 功能一:实现拖拽 思 ...

  7. javaweb学习5——JSP

    声明:本文只是自学过程中,记录自己不会的知识点的摘要,如果想详细学习JavaWeb,请到孤傲苍狼博客学习,JavaWeb学习点此跳转 本文链接:https://www.cnblogs.com/xdp- ...

  8. 解决Unity烘焙阴影锯齿精度不足的问题

    烘焙阴影锯齿问题  烘焙后阴影锯齿明显,如下图: 烘焙的光照贴图质量主要受LightmapParameters 的Blur Radius和抗锯齿级别影响, 默认最高级别如下: 如果最高级别不能达到好的 ...

  9. Python创建虚拟环境

    用于创建和管理虚拟环境的模块称为 venv.venv 通常会安装你可用的最新版本的 Python.如果您的系统上有多个版本的 Python,您可以通过运行 python3 或您想要的任何版本来选择特定 ...

  10. 小强版之无码理解C语言指针

     1. 先从普通变量开始   2. 撸完变量撸指针   3. 故事情节进一步发展,此处少儿不宜   4. 奶茶妹妹捉奸,小强死定了   5. 源码欣赏  #include <stdio.h> ...