【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的意义是?????/?

【C\/C++】如何判断指针式malloc\/new分配出来的
第一个,数据量大的话效率比较低。malloc是你自己程序调用的,那你就把malloc出来的地址记录下来不就好了,只要判断是不是有该地址,就知道是不是malloc出来的了,这种方法效率比较低,每次判断都要遍历你的地址池。第二个,效率很高。首先在main函数开头随便创建2个变量,用于获取堆区起始位置和增长方向。下...

关于C++ new和malloc的区别,记住这张表格就行了!
new是C++中的关键字,用于在运行时分配内存,分配成功时返回与对象类型匹配的指针,不需要进行类型转换。malloc是C语言中的库函数,用于在堆上分配内存,返回void*类型的指针,需要通过强制类型转换来使用。在内存分配时,new和malloc在内存位置上的区别主要在于new分配的内存通常位于自由存储区,而malloc分配...

c\/c++怎样检测指针是否已经分配空间
如果你说 p = new int[2];才算是分配内存,那我告诉你,这句话的意思:通过new 向系统申请sizeof(int) * 2的内存大小,接下来把这块内存的地址返回,并保存在p中。并不是说p有2个int大小的内存呢。~~~int * p和int p 一样,声明的时候就分配了内存。if ( p )是判断p是否保存了一块...

C++中new出得对象与C中的malloc出得有什么联系和区别?
1、new 是c++中的操作符,malloc是c 中的一个函数 2、new 不止是分配内存,而且会调用类的构造函数,同理delete会调用类的析构函数,而malloc则只分配内存,不会进行初始化类成员的工作,同样free也不会调用析构函数 3、内存泄漏对于malloc或者new都可以检查出来的,区别在于new可以指明是那个文件的那...

经典面试题之new和malloc的区别
属性上,new和delete是C++语言的关键字,需要编译器支持,而malloc和free是库函数,需要包含头文件。new操作符在申请内存时无需指定大小,它会根据类型信息自行计算。相反,malloc函数需要显式指定所需内存的尺寸。new操作符返回的对象类型指针,与申请的对象类型严格匹配,无需进行类型转换。而malloc成功分配...

new和malloc区别
首先,malloc是C语言标准库中的一个函数,它用于分配一定数量的内存空间。在使用malloc时,需要指定需要分配的内存大小。malloc会根据可用内存的情况,分配相应大小的内存空间,并返回指向这块内存的指针。如果内存分配失败,malloc会返回NULL。相比之下,new是C++中用于内存分配的运算符。它与malloc不同,它会...

new与malloc的区别以及实现方法
1. malloc和free是库函数,而new和delete是C++操作符;2. new自动计算所需空间大小,例如“int *a = new”,而malloc需要指定大小,例如“int *a = malloc(sizeof(int))”;3. new在动态分配内存时可以初始化对象,调用其构造函数,delete在释放内存时调用对象的析构函数。而malloc只分配一段给定...

C++\/C 内存分配-malloc\/mmap\/syscall深度解析以及性能测试
malloc和free是C语言库函数,而在C++中常用的是new和delete,C里面是用malloc_stats();而C++则需要用\/proc\/self\/smaps文件来查看进程的内存映射情况 ,但是大块内存无法用这个查看,比如mmap分配的。需要其他内存分析工具 A:他们直接的区别 new和delete是C++中的运算符,而malloc和free是C语言中的函数。

new和malloc的区别
重载方面,C++允许new和delete操作符重载。new不仅分配内存,还可以指定地址,调用构造函数初始化对象,并返回对象指针。而malloc不允许重载,只能分配内存,无法执行构造函数。自定义类型处理中,new通过调用operator new函数分配内存、调用构造函数初始化对象,返回对象指针。delete则先调用析构函数,再调用...

malloc和new的区别是什么?
1、申请的内存所在位置不同 new操作符从自由存储区(free store)上为对象动态分配内存空间。自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。malloc函数从堆上动态分配内存。堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序的内存动态...

相似回答