繁体   English   中英

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

[英]How can I free memory in C when a pointer is not known?

我希望释放没有指针的内存块。 在我的程序中,我顺序调用malloc ,希望由malloc(1)malloc(4)malloc(5)创建的malloc(1)是连续的。 然后,当我只有指向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);
}

无法做自己想做的事。 甚至都不应该尝试做您想做的事。

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

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

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

如果这看起来需要大量工作,则可以考虑使用托管语言,例如C#或Java或Python或其他任何语言。

free(void*)

[deallocate]先前由对malloccallocrealloc的调用分配的一块malloc被释放,使其再次可用于进一步的分配。

如果ptr不指向分配有上述功能的内存块,则会导致未定义的行为 -http://www.cplusplus.com/reference/cstdlib/free/

不可能。

但我想不到如何做到这一点

那是因为不可能。 malloc获得的块可以按任意顺序出现。 释放动态分配的内存块的唯一方法是使程序可以访问它的指针。 其他都是未定义的行为。

注意: malloc实现执行“簿记”,以查明要释放的块类型。 尽管入侵它们的实现并非不可能,但没有办法以符合标准的,可移植的方式来实现。

出于多种原因,您无法创建[-5] ...事物,但是从实际的角度出发,您必须记住,使用malloc()分配的malloc()正在从堆中移出,而不是从堆栈中移出,以便“计数”为从其他地方很难做到这一点(因为不能保证对malloc的多次调用是顺序的)。

当指针在没有释放的情况下失去与内存的关联(或超出范围)时发生的事情称为内存泄漏,并且没有C中不易使用的详尽技术(例如Java的标记/清除垃圾收集,或m分配整个内存和扫描它或其他东西)无法回收此内存。

因此,当指针未知时,您将无法释放C中的内存。

这绝不是对您所做工作的认可,但是可以假设您知道块是连续分配的

例如:

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));
}

首先-似乎您不了解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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM