当指针未知时,如何在C中释放内存?

时间:2014-09-12 16:09:53

标签: c pointers memory memory-management

我想释放一些我没有指向的内存块。在我的程序中,我按顺序调用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);
}

6 个答案:

答案 0 :(得分:7)

不能做你想做的事。你甚至不应该尝试来做你想做的事。

即使你确切地知道malloc()正在做什么,你的程序也会依赖于未定义的行为。当新版本的C库到来时,行为可能会改变,如果您使用不同的工具链(从GNU C切换到Microsoft C或其他任何工具链)编译它,您的程序几乎肯定会失败。

每次分配内存时,都需要跟踪指针。如果您的程序甚至不知道内存,则无法释放它。

跟踪您的内存分配。如果要设计要动态分配的数据结构,则您的设计应包含跟踪它们的功能,例如在链接列表中保留地址列表等。

如果这看起来很多,可以考虑使用C#或Java或Python等托管语言。

答案 1 :(得分:2)

  

<强> free(void*)

     

[deallocate]先前通过调用malloccallocrealloc分配的内存块已取消分配,再次可用于进一步分配。

     

如果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);