【C/C++】如何判断指针式malloc/new分配出来的

问题是这样的,输入时一个指针,要判断出指针是否是为malloc返回出来的。
补充: malloc 在分配堆上的地址空间后,会维护一个全局的表或者是在分配地址空间的前面记录分配的内存信息,供free的时候使用。 现在我要求提供一种方法可以,访问这些信息,并通过信息得到,此段内存是否为malloc分配出来的,内存实际大小多少。(不要说判断指针是否为空,养成一个良好的编程习惯,自己重写个malloc然后保存所有分配信息。这些我已经考虑过了,但是普适性不强,要求至少在一种编译器或者操作系统下,这个方法对于判断所有的指针都适用。)
不是要区分这个指针到底是malloc,还是new return的。就像你说的,new的内部也会调用malloc,只是多了构造的步骤。 简单的说,就是要区分出这个地址是否是malloc 分配出来的,还是别人随便写的一个地址。举个例子吧: 比如有三个指针,a=malloc(sizeof(int*100)); b = a+10; c = 0xCCCCC43fa. 我要判断出,指针a 合法,b和c 非法。

to: 玉铉 应该会在内存中, 因为如果你编译一个程序,可以接收外面传进来的内存,处理,最后可以释放掉。这样就可以知道,你在编译的时候free() 是不会知道要如何释放内存,所以这个表肯定在内存中。 同样,自己定义的MyMalloc也不会知道如何释放内存。

巨简单,提供两个方法,自行按照运行效率选择。
第一个,数据量大的话效率比较低。malloc是你自己程序调用的,那你就把malloc出来的地址记录下来不就好了,只要判断是不是有该地址,就知道是不是malloc出来的了,这种方法效率比较低,每次判断都要遍历你的地址池。
第二个,效率很高。首先在main函数开头随便创建2个变量,用于获取堆区起始位置和增长方向。下面就很简单了,你程序里面所有的变量要不就是栈区的,要不就是堆区的,要不就是静态和常量,那么你知道了堆区大概范围,只要判断对象是不是在该范围内不就能逆向推理出是不是malloc出来的了吗

//GC堆空间大小,此处为4096B
const int HEAP_SIZE=0x1000;
//GC堆空间阈值,超过该阈值GC会开始运行
int HEAP_Threshold=STACK_SIZE*0.8;
//GC堆空间起始地址
int HEAP_START_ADDR;
//GC堆空间结束地址
int HEAP_END_ADDR;
//程序堆空间增长方向
int HEAP_DIRECTION;
//获取GC堆空间起始地址和结束地址
HEAP_START_ADDR=(int*)malloc(1);
int TEMP=(int*)malloc(1);
//获取堆增长方向
HEAP_DIRECTION=(TEMP-HEAP_START_ADDR)>0?1:-1;
HEAP_END_ADDR=HEAP_START_ADDR+(HEAP_SIZE-1)*HEAP_DIRECTION;
if(HEAP_DIRECTION<0){
HEAP_START_ADDR=HEAP_END_ADDR+HEAP_START_ADDR;
HEAP_END_ADDR=HEAP_START_ADDR-HEAP_END_ADDR;
HEAP_START_ADDR=HEAP_START_ADDR-HEAP_END_ADDR;
}
free((int*)HEAP_START_ADDR);
free((int*)TEMP);
温馨提示:答案为网友推荐,仅供参考
第1个回答  2010-05-12
这没戏的, 有些C++里的new/delete就是调用malloc/free实现内存分配的, win上的实现多半是都用heapalloc实现,这些信息基本上该有的都有了。 当然这不代表这两组东西就一样了, 因为new/delete多了一个步骤就是调用构造/析构函数

这种问题一般就是尽量别用malloc。 如果你写了一些函数,里面某个分配了内存给外头, 为了防止别人不清楚你用的是malloc还是new, 你最好写一个对应的释放内存函数
第2个回答  2010-05-19
本身来说这个事情是不可能的
因为这个表是由编译器构造的
而且就在X86,ARM, SPARC,或者常用的What ever linux/unix, windows, symbianOS平台上来说 malloc 跟 new 之于内存没有根本的关系, 都是操作系统跟cpu的分页调度, 地址转换之间玩的小把戏.
=====================================================
回下楼主
可能这个还是你对程序的运行理解不够明确吧, 我们就拿Unix类跟Windows这两个使用最广泛的系统来做说明

无论是那个系统, 在调用malloc后最后都会转到系统调用, 换句话说都会转入内核态,

Windows下 malloc->heapalloc->ntvirtualalloc->通过ssdt一个跳转转到系统控制的内核态进行处理

unix类系统下 根据申请内存的大小是否满足内存的一个页 来分别调用不同的系统调用, 大多数被slab分配器处理

这个没有听说过也没有关系

不知道你注意没有 无论你的程序再怎么变态, 泄露的内存再多, 只要你的程序退出, 绝对不会影响到系统的内存控制

只要你注意到了这个细节,你就会发现, 这个表其实是不存在与你的程序之中的, 或者说, 不存在于你的进程空间之中,

X86下的32位系统为每个进程提供了独立的4G空间, 无论你申请也好, 释放也好, 都在这个4G的空间内, 那么就明显了, 这个4G的空间本身就有个表在维护, 但是他跟你的进程没有关系.

你想获得这个表, 那就要去访问内核态空间, 访问系统底部的控制, 但是这跟通用完全是矛盾的, 先不说硬件级别的, 单单是不同系统间的内存控制就不可能相同, 普适性无从谈起.
===================================================
另外 我仔细看了看k19862217的程序 这样不能解决问题
假设在类中虚拟空间分配了内存P
在外部有野指针W 其值正好等于P
那么对W的判断返回则是malloc分配的内存
不可行

如果想要自己维护这个表的话
维护的不仅仅是已经分配的内存表
还需要一张指针表, 记录所有的指针初始化信息
程序段不只是这么简单
在性能上 不被允许本回答被提问者采纳
第3个回答  2010-05-19
可以自己定义malloc和free,将原来的malloc和free屏蔽掉,然后定义个链表来管理内存空间,做了个简单的例子,你参考下
//MyMalloc.h
#ifndef _MYMALLOC_H_
#define _MYMALLOC_H_

typedef struct malloc_info{
void * address;
int size;
struct malloc_info * next;
}malloc_info;

//声明自定义malloc及free函数
extern void *MyMalloc(unsigned int uSize);
extern int MyFree(void *pPtr);
extern malloc_info * GetInfo(void *pPtr);

//重定义malloc及free
#define malloc(size) MyMalloc(size)
#define free(ptr) MyFree(ptr);

#endif

//MyMalloc.c
#include <stdio.h>
#include <stdlib.h>

typedef struct malloc_info{
void * address;
int size;
struct malloc_info * next;
}malloc_info;

static malloc_info* base = NULL;
void * MyMalloc(unsigned int size) {
malloc_info * tmp = base;
if(!base) {
base = (malloc_info *)malloc(sizeof(malloc_info));
base->address = malloc(size);
if (!base->address)
return NULL;
base->size = size;
base->next = NULL;
return base->address;
} else {
while(tmp->next) {
tmp = tmp->next;
}
tmp->next = (malloc_info *)malloc(sizeof(malloc_info));
tmp->next->address = malloc(size);
if (!tmp->next->address)
return NULL;
tmp->next->size = size;
tmp->next->next = NULL;
return tmp->next->address;
}
return NULL;
}

int MyFree(void * address) {
malloc_info * tmp = base;
malloc_info * next;
if (base && base->address == address) {
base = base->next;
free(tmp->address);
free(tmp);
return 0;
}
while(tmp) {
next = tmp->next;
if (next) {
if (next->address == address) {
tmp->next = next->next;
free(next->address);
free(next);
return 0;
}
}
}
return 0;
}

malloc_info * GetInfo(void * address){
malloc_info * tmp = base;
while(tmp) {
if(tmp->address == address) {
return tmp;
}
}
return NULL;
}
//test.c
#include <stdlib.h>
#include <stdio.h>
#include "MyMalloc.h"

int main()
{
char * arr;
malloc_info * tmp;
arr = (char *)malloc(100 * sizeof(int));
tmp = GetInfo((void *)arr);
if (tmp) {
printf("size is %d\n" ,tmp->size);
}
free(arr);
getchar();
}
补充一下,如果像你想要的那样想判断合法与非法,用GetInfo,如果返回为NULL代表非法,非NULL就反回了这块内存的信息,包括地址的大小,如果想要其他信息的话你修改下结构体就行了,然后链表处理的部分你在好好看看,我着急没太仔细想就写了
第4个回答  2010-05-18
int * p = (int*)malloc(4);//假设p=0x5201314
//嗯 p是malloc的
free(p);
//p还是0x5201314,判断是否为malloc的意义是?????/?
相似回答