2014-09-12 126 views
0

我希望释放我没有指针指向的内存块。在我的程序中,我依次调用malloc,希望由malloc(1),malloc(4),malloc(5)创建的内存是连续的。然后当我只有指向malloc(5)的指针时,我释放这些内存。但我想不出如何做到这一点;我不能简单地创建一个指向ptr [-5]的地址的指针,然后释放5个字节的内存?如何才能做到这一点?当指针未知时,如何在C中释放内存?

#include <string.h> 
#include <stdio.h> 
#include <stdlib.h> 

int main(){ 

    malloc(1); 
    malloc(4); 
    char* ptr = malloc(5); 

    free(ptr); 
} 
+5

为什么你的malloc在那样摆在首位野外? – JBL 2014-09-12 16:12:33

+5

为什么?为什么?如果你想连续的内存,分配一个调用'malloc'并做一些指针算术。这只会导致未定义的行为。 – 2014-09-12 16:12:34

+3

希望内存分配是连续的,似乎相当乐观:) – 2014-09-12 16:14:13

回答

7

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

即使您正确计算malloc()正在做什么,您的程序将依赖未定义的行为。当C库的新版本到达时,行为可能会发生变化,如果使用不同的工具链(从GNU C切换到Microsoft C或其他)编译它,程序几乎肯定会失败。

无论何时你分配内存,你都需要跟踪指针。如果你的程序甚至不知道内存,就没有办法释放它。

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

如果这看起来像很多工作,也许考虑使用托管语言,如C#或Java或Python或其他。

+1

Upvoted,但我会补充说它不仅仅是你不能这样做,没有必要去做。 'malloc()'说'给我一些内存',返回值是内存的地址。如果你立即放弃返回值,那么你不能使用内存(更不用说释放它),所以为什么要首先要求它? – abligh 2014-09-12 16:19:55

+0

那么,这个问题上的示例代码是愚蠢的,但它似乎可能是实际的程序正在做指针的东西,只是不打扰跟踪它们。我编写了一些调用'malloc()'的简单程序,而不需要跟踪内存,因为程序在终止时会释放所有的资源。但是我的专业动态程序全都跟踪每一个分配,我运行Valgrind以确保它们永不泄漏内存。 http://stackoverflow.com/a/1529832/166949 – steveha 2014-09-12 16:29:26

2

free(void*)

[DEALLOCATE]先前由呼叫分配给malloccallocrealloc的存储器块被重新分配,使得它再次可用于进一步的分配。

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

没有办法。

2

但我想不出如何可以做到这一点

这是因为它是不可能的。您从malloc获得的块可以按照任意顺序进行。释放一个动态分配的内存块的唯一方法是保持一个指向它的程序可访问的指针。其他任何东西都是未定义的行为。

注意:malloc的实施执行“簿记”来找出你正在释放什么样的块。尽管侵入他们的实施并非不可能,但是以符合标准的便携方式无法做到这一点。

1

由于各种原因,您不能创建[-5] ...事物,但从实际的角度来看,您必须记住,使用malloc()分配的内存将从堆中分离出来,从而“计数“从其他地方到它很难(因为多次调用malloc不能保证顺序)。

当指针失去与内存的关联(或超出范围)而未被释放时会发生什么?称为内存泄漏,并且没有在C中不可用的穷举技术(例如Java标记/清理垃圾回收或mallocing整个内存和扫描它的东西),这是不可能的回收这个内存。

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

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