修剪时realloc是否会失败(返回NULL)?

修剪时realloc是否会失败(返回NULL)?,c,memory-management,realloc,C,Memory Management,Realloc,如果要执行下一步: int* array = malloc(10 * sizeof(int)); 我使用realloc: array = realloc(array, 5 * sizeof(int)); 在第二行(并且只有它一行),它是否可以返回NULL?realloc不会在收缩现有内存时失败,因此它不会返回NULL。只有在扩展过程中失败时,它才能返回NULL 但是在某些体系结构中,收缩可能会失败,realloc可以以不同的方式实现,比如单独分配较小的内存,释放旧内存以避免碎片。在这种情况下

如果要执行下一步:

int* array = malloc(10 * sizeof(int));
我使用realloc:

array = realloc(array, 5 * sizeof(int));

在第二行(并且只有它一行),它是否可以返回
NULL

realloc
不会在收缩现有内存时失败,因此它不会返回
NULL
。只有在扩展过程中失败时,它才能返回
NULL

但是在某些体系结构中,收缩可能会失败,
realloc
可以以不同的方式实现,比如单独分配较小的内存,释放旧内存以避免碎片。在这种情况下,收缩内存可能返回NULL。但它的实现非常罕见


但最好是安全一点,在收缩内存后保持
NULL
检查。

realloc
不会在收缩现有内存时失败,因此它不会返回
NULL
。只有在扩展过程中失败时,它才能返回
NULL

但是在某些体系结构中,收缩可能会失败,
realloc
可以以不同的方式实现,比如单独分配较小的内存,释放旧内存以避免碎片。在这种情况下,收缩内存可能返回NULL。但它的实现非常罕见

但最好是更安全一点,在收缩内存后保持
NULL
检查。

语言(和库)规范没有这样的保证,就像它不保证“修剪”
realloc
将保留指针值一样

实现可能决定以最“原始”的方式实现
realloc
:对新内存块执行无条件的
malloc
,复制数据并
释放旧内存块。显然,这种实现在内存不足的情况下可能会失败。

语言(和库)规范没有这样的保证,就像它不保证“修剪”
realloc
将保留指针值一样


实现可能决定以最“原始”的方式实现
realloc
:对新内存块执行无条件的
malloc
,复制数据并
释放旧内存块。显然,这种实现在内存不足的情况下可能会失败。

不要指望它。本标准未作此规定;它只声明“如果无法分配新对象,则为空指针”


您很难找到这样的实现,但根据标准,它仍然是兼容的。

不要指望它。本标准未作此规定;它只声明“如果无法分配新对象,则为空指针”


您很难找到这样的实现,但根据标准,它仍然是兼容的。

是的,它可以。realloc()
上没有实现保证,即使收缩,它也可以返回不同的指针

例如,如果一个特定的实现对不同的对象大小使用不同的池,
realloc()。因此,如果较小对象的池已满,它将失败并返回
NULL


或者,它可能会简单地决定最好移动块

我只是使用了以下程序来获得glibc实际分配内存的大小:

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

int main()                                                                   
{                                                                            
    int n;                                                                   

    for (n = 0; n <= 10; ++n)                                                
    {                                                                        
        void* array = malloc(n * sizeof(int));                               
        size_t* a2 = (size_t*) array;                                        

        printf("%d -> %zu\n", n, a2[-1]);                                    
    }                                                                        
}
#包括
#包括
int main()
{                                                                            
int n;

对于(n=0;n是,它可以。
realloc()
上没有实现保证,即使在收缩时它也可以返回不同的指针

例如,如果一个特定的实现对不同的对象大小使用不同的池,
realloc()
实际上可能会在池中为较小的对象分配一个新块,并为较大的对象释放池中的块。因此,如果较小对象的池已满,它将失败并返回
NULL


或者,它可能会简单地决定最好移动块

我只是使用了以下程序来获得glibc实际分配内存的大小:

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

int main()                                                                   
{                                                                            
    int n;                                                                   

    for (n = 0; n <= 10; ++n)                                                
    {                                                                        
        void* array = malloc(n * sizeof(int));                               
        size_t* a2 = (size_t*) array;                                        

        printf("%d -> %zu\n", n, a2[-1]);                                    
    }                                                                        
}
#包括
#包括
int main()
{                                                                            
int n;
对于(n=0;n我怀疑在您描述的场景中可能存在理论上的失败可能性

根据堆实现的不同,可能没有修剪现有分配块这样的事情。相反,首先分配较小的块,然后从旧块复制数据,然后释放数据

例如,bucket heap策略(由一些流行的堆使用,例如tcmalloc)可能就是这种情况。

我怀疑,在您描述的场景中,理论上可能存在失败的可能性

根据堆实现的不同,可能没有修剪现有分配块这样的事情。相反,首先分配较小的块,然后从旧块复制数据,然后释放数据


例如,bucket heap策略(一些流行的堆使用,如tcmalloc)可能就是这种情况。

其他答案已经解决了这个问题,但是假设您知道
realloc
调用是一个“修剪”,您可以用以下内容来包装它:

void *safe_trim(void *p, size_t n) {
    void *p2 = realloc(p, n);
    return p2 ? p2 : p;
}
并且返回值将始终指向