我想释放一些我没有指向的内存块。在我的程序中,我按顺序调用malloc
,希望malloc(1)
,malloc(4)
,malloc(5)
创建的内存是连续的。然后,当我只有指向malloc(5)
的指针时,我释放这些内存。但我无法想到如何做到这一点;我不能简单地创建一个引用ptr [-5]地址的指针,然后释放5个字节的内存?如何才能做到这一点?
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(){
malloc(1);
malloc(4);
char* ptr = malloc(5);
free(ptr);
}
答案 0 :(得分:7)
你不能做你想做的事。你甚至不应该尝试来做你想做的事。
即使你确切地知道malloc()
正在做什么,你的程序也会依赖于未定义的行为。当新版本的C库到来时,行为可能会改变,如果您使用不同的工具链(从GNU C切换到Microsoft C或其他任何工具链)编译它,您的程序几乎肯定会失败。
每次分配内存时,都需要跟踪指针。如果您的程序甚至不知道内存,则无法释放它。
跟踪您的内存分配。如果要设计要动态分配的数据结构,则您的设计应包含跟踪它们的功能,例如在链接列表中保留地址列表等。
如果这看起来很多,可以考虑使用C#或Java或Python等托管语言。
答案 1 :(得分:2)
<强>
free(void*)
强>[deallocate]先前通过调用
malloc
,calloc
或realloc
分配的内存块已取消分配,再次可用于进一步分配。如果ptr没有指向使用上述功能分配的内存块,则会导致未定义的行为。 - http://www.cplusplus.com/reference/cstdlib/free/
没有办法。
答案 2 :(得分:2)
但我想不出如何做到这一点
那是因为这是不可能的。您从malloc
返回的块可以按任意顺序排列。释放动态分配的内存块的唯一方法是保持程序可以访问它的指针。其他任何事都是未定义的行为。
注意: malloc
执行“簿记”以确定您要发布的块类型。虽然攻击它们的实现并非不可能,但是没有办法以符合标准的可移植方式进行。
答案 3 :(得分:1)
你不能因为各种原因创建一个[-5] ...的东西,但从实际的角度来看,你必须记住,用malloc()
分配的内存是从堆中而不是堆栈那么到&#34;计算&#34;从其他地方来到它很困难(因为不能保证对malloc的多次调用是连续的)。
当指针在没有被释放的情况下失去与内存的关联(或超出范围)时会发生什么事情被称为内存泄漏,并且在C中没有详尽的技术(例如Java的标记/清除垃圾收集) ,或者整理内存并扫描它或其他内容)无法回收这个内存。
因此,当指针未知时,你无法在C中释放内存。
答案 4 :(得分:1)
这绝不是对你所做的事情的认可,但是假设你知道这些块是连续分配的。
例如:
int main(){
char* ptr1=malloc(1);
char* ptr2=malloc(4);
char* ptr3=malloc(5);
// Verify that the memory is in fact continuous.
assert(ptr3==(ptr2+4));
assert(ptr3==(ptr1+5));
free(ptr3); // Frees 5 bytes at ptr3
free(ptr3-4); // Frees 4 bytes at ptr2
free(ptr3-5); // Frees 1 byte at ptr1
}
所以,如果你有一个指针并且知道你在它之前分配了一组连续字节的事实,你可以用指针算法简单地偏移指针。这是非常危险的,不推荐,但它是可能的。
修改强>
我运行了一个测试程序,在我的架构上,它分配了32个字节的块,所以ptr1 + 32 == ptr2,ptr2 + 32 = ptr3。它为任何小于或等于24字节的块执行此操作。因此,如果我分配24或更少,那么每个ptr将比前一个大32个字节。如果我分配了25个或更多,那么它又分配了16个字节,总计48个。
因此,在我的架构中,你需要在使用指针算法生成指针方面更有创意,因为它不能按预期工作。
这是一个示例程序,适用于我的架构中所有大小的ptr1,ptr2和ptr3 。
#define ROUNDUP(number, multiple) (((number + multiple -1)/multiple)*multiple)
#define OFFSET(size) ((size < 24) ? 32 : ROUNDUP(size+8,16))
int main(int argc, char* argv[]){
char* ptr1, *ptr2, *ptr3;
int s1=atoi(argv[1]);
int s2=atoi(argv[2]);
int s3=atoi(argv[3]);
ptr1=(char*)malloc(s1);
ptr2=(char*)malloc(s2);
ptr3=(char*)malloc(s3);
fprintf(stdout, "%p %p %p\n", ptr1, ptr2, ptr3);
assert(ptr3==(ptr2+OFFSET(s2)));
assert(ptr2==(ptr1+OFFSET(s1)));
// Try to construct ptr2 from ptr3.
free(ptr3);
free(ptr3-OFFSET(s2));
free(ptr3-OFFSET(s2)-OFFSET(s1));
}
答案 5 :(得分:1)
首先 - 因为您似乎无法理解malloc
的工作原理 - 将连续数字传递给malloc
,不会使其分配数组。 malloc
定义如下:
void* malloc (size_t size);
虽然整数可以转换为size_t
,但它仍然是分配的字节数,而不是元素数。如果要分配数组,请按以下步骤操作:
int* myDynamicArray = malloc(sizeof(int)*numberOfElements);
然后,您可以通过执行以下操作来访问元素:
int i;
for(i=0;i<numberOfElements;i++)
printf("%d",myDynamicArray[i]);
然后,像其他人指出的那样 - 你可以通过调用free
函数来释放内存。 free
定义如下:
void free (void* ptr);
你只需按照以下方式调用它:
free(myDynamicArray);