Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如果我们需要一个“tmp缓冲区”,为什么要使用“realloc”`_C_Malloc_Realloc - Fatal编程技术网

如果我们需要一个“tmp缓冲区”,为什么要使用“realloc”`

如果我们需要一个“tmp缓冲区”,为什么要使用“realloc”`,c,malloc,realloc,C,Malloc,Realloc,至于我所关心的,如果realloc失败,我们将丢失信息并realloc将缓冲区(指针)设置为NULL 考虑以下计划: #include<stdio.h> #include<stdlib.h> #include<string.h> int main(void){ char *ptr = malloc(256); if (!ptr){ printf("Error, malloc\n"); exit(1);

至于我所关心的,如果
realloc
失败,我们将丢失信息并
realloc
将缓冲区(指针)设置为
NULL

考虑以下计划:

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

int main(void){
    char *ptr = malloc(256);

    if (!ptr){
        printf("Error, malloc\n");
        exit(1);
    }

    strcpy(ptr, "Michi");

    ptr = realloc (ptr, 1024 * 102400000uL); /* I ask for a big chunk here to make realloc to fail */

    if (!ptr){
        printf("Houston we have a Problem\n");
    }

    printf("PTR = %s\n", ptr);

    if (ptr){
        free(ptr);
        ptr = NULL;
    }
}
我刚刚丢失了
ptr
中的信息

现在要解决这个问题,我们应该先使用一个临时缓冲区(指针),看看我们是否得到了那块内存,如果得到了,我们可以使用它,如果没有,我们仍然可以使用主缓冲区(指针)

现在请考虑下面的程序,而不是调用<代码> ReloLC/<代码>,我在临时缓冲区(指针)上调用<代码> MalOC :

现在,我为什么要使用
realloc

基于此上下文,使用
realloc
而不是
malloc
有什么好处吗?

您的问题在于如何使用
realloc
。您不必将
realloc
的结果分配给重新分配的同一个指针。正如您所指出的,如果
realloc
失败,它甚至会带来问题。如果您立即将结果分配给
ptr
,那么当出现问题时,确实会丢失以前的缓冲区。但是,如果将
realloc
的结果分配给
tmpPTR
,则即使
realloc
失败,
ptr
仍保持良好状态。使用
realloc
如下:

char * ptr = malloc(256);
if(!ptr){
    return 1;
}

char * tmpPTR = realloc(ptr, 512);
if(!tmpPTR){
    printf("Houston, we have a problem");
    // ptr is fine
}else{
    ptr = tmpPTR;
}

// ptr is realloc()ed
在上面的代码中,
tmpPTR
不是一个新的(临时)缓冲区,而是一个(临时)指针。如果
realloc
成功,它将指向相同的缓冲区(但可能位于不同的位置),如果失败,它将为
NULL
realloc
并不总是需要分配新的缓冲区,但可以更改现有的缓冲区以适应新的大小。但如果失败,则不会更改原始缓冲区

如果将
malloc
与临时缓冲区一起使用,则(在本例中)至少需要256+512=768字节,并且始终需要复制旧数据
realloc
可能能够重复使用旧的缓冲区,因此不需要复制,并且您不会使用超过请求的内存


您可以使用
malloc
方法,但是
realloc
几乎总是更有效。

realloc方案很简单。您不需要单独调用
malloc
。例如,如果您最初为
ptr
分配了
256
字节,只需使用计数器(或下面的索引,
i
)即可跟踪分配给
ptr
的块中有多少内存已被使用,以及计数器何时达到限制(如果使用
ptr
作为字符串,则1小于基于0的索引的最大值,或2小于最大值),
realloc

下面显示了一个方案,您只需在每次达到分配限制时向
ptr
添加
256
额外字节:

int i = 0, max = 256;
char *ptr = malloc(max);

/* do whatever until i reaches 255 */

if (i + 1 >= max) {
    void *tmp = realloc (ptr, max + 256);
    if (!tmp) {
        fprintf (stderr, "error: realloc - memory exhausted.\n")
        /* handle error */
    }
    ptr = tmp;
    max += 256;
}
注意:您的
处理错误
可以退出任何循环以保留
ptr
中的现有数据。您不需要在该点退出

现在要解决这个问题,我们应该先使用一个临时缓冲区(指针),看看我们是否得到了那块内存,如果得到了,我们可以使用它,如果没有,我们仍然可以使用主缓冲区(指针)

这不仅没有帮助,而且让事情变得更糟,因为现在你不再有指向你试图重新分配的块的指针。那么你如何
释放它呢

因此:

  • 浪费内存
  • 需要额外分配、复制和免费
  • 由于1,使得
    realloc
    更有可能失败
  • 由于指向试图重新分配的块的指针丢失,内存泄漏

  • 因此,不,这不是处理返回NULL的
    realloc
    的好方法。在调用
    realloc
    时保存原始指针,以便能够理智地处理故障。
    realloc
    的目的是避免您必须管理两个数据副本,甚至避免在可能的情况下创建它们。所以让
    realloc
    不要这样做无论何时,他都会为你工作。

    malloc
    相比,
    realloc
    的优势在于,它可能能够扩展原始动态内存区域,因此无需复制所有以前的元素;你不能用
    malloc
    1来做这件事。而这种优化是否可用,对你来说都没有成本美国


    假设您有一个以前分配的指针:

    char *some_string = malloc(size); // assume non-NULL
    
    然后

    在(1)处,您用新指针更新旧指针。可能会发生两种情况:地址已有效更改(元素已自动复制)或未更改-您并不在乎。无论哪种情况,您的数据现在都位于
    某个\u字符串


    只有实际的实现(OS/libc)知道是否有可能放大块:你看不到它,它是一个实现细节。但是,你可以检查你的实现代码,看看它是如何实现的。

    从技术上讲,这是不必要的,因为它执行的是完全相同的任务

    我经常读取长度不确定的输入。在下面的函数示例中,我很少使用
    malloc()
    ,而是广泛使用
    realloc()

    #include <stdlib.h>
    #include <errno.h>
    
    struct record {
        /* fields in each record */
    };
    
    struct table {
        size_t         size;   /* Number of records allocated */
        size_t         used;   /* Number of records in table */
        struct record  item[]; /* C99 flexible array member */
    };
    
    #define MAX_ITEMS_PER_READ 1
    
    struct table *read_table(FILE *source)
    {
        struct table  *result = NULL, *temp;
        size_t         size = 0;
        size_t         used = 0, n;
        int            err = 0;
    
        /* Read loop */
        while (1) {
    
            if (used + MAX_ITEMS_PER_READ > size) {
                /* Array size growth policy.
                 * Some suggest doubling the size,
                 * or using a constant factor.
                 * Here, the minimum is
                 *     size = used + MAX_ITEMS_PER_READ;
                */
                const size_t  newsize = 2*MAX_ITEMS_PER_READ + used + used / 2;
    
                temp = realloc(result, sizeof (struct table) + 
                                       newsize * sizeof (result->item[0]));
                if (!temp) {
                    err = ENOMEM;
                    break;
                }
    
                result = temp;
                size = newsize;
            }
    
            /* Read a record to result->item[used],
             * or up to (size-used) records starting at result->item + used.
             * If there are no more records, break.
             * If an error occurs, set err = errno, and break.
             *
             * Increment used by the number of records read: */            
            used++;
        }
    
        if (err) {
            free(result); /* NOTE: free(NULL) is safe. */
            errno = err;
            return NULL;
        }
    
        if (!used) {
            free(result);
            errno = ENODATA; /* POSIX.1 error code, not C89/C99/C11 */
            return NULL;
        }
    
        /* Optional: optimize table size. */
        if (used < size) {
            /* We don't mind even if realloc were to fail here. */
            temp = realloc(result, sizeof (struct table) + 
                                   used * sizeof table->item[0]);
            if (temp) {
                result = temp;
                size = used;
            }
        }
    
        result->size = size;
        result->used = used;
    
        errno = 0; /* Not normally zeroed; just my style. */
        return result;
    }
    
    #包括
    #包括
    结构记录{
    /*每个记录中的字段*/
    };
    结构表{
    大小\u t大小;/*分配的记录数*/
    使用的大小;/*表中的记录数*/
    结构记录项[];/*C99灵活数组成员*/
    };
    #定义每个读取的最大项目数1
    结构表*读取表(文件*源)
    {
    结构表*result=NULL,*temp;
    大小\u t大小=0;
    使用的尺寸=0,n;
    int err=0;
    /*读循环*/
    而(1){
    如果(已使用+每个读取的最大项目>大小){
    /*阵列大小增长策略。
    *有人建议将规模扩大一倍,
    *或者使用常数因子。
    *在这里,最小值是
    
    int i = 0, max = 256;
    char *ptr = malloc(max);
    
    /* do whatever until i reaches 255 */
    
    if (i + 1 >= max) {
        void *tmp = realloc (ptr, max + 256);
        if (!tmp) {
            fprintf (stderr, "error: realloc - memory exhausted.\n")
            /* handle error */
        }
        ptr = tmp;
        max += 256;
    }
    
    char *some_string = malloc(size); // assume non-NULL
    
    if (realloc_needed) {
          char *tmp = realloc(some_string, new_size);
    
         if ( tmp == NULL ) 
              // handle error
         else
             some_string = tmp; // (1)
    
    #include <stdlib.h>
    #include <errno.h>
    
    struct record {
        /* fields in each record */
    };
    
    struct table {
        size_t         size;   /* Number of records allocated */
        size_t         used;   /* Number of records in table */
        struct record  item[]; /* C99 flexible array member */
    };
    
    #define MAX_ITEMS_PER_READ 1
    
    struct table *read_table(FILE *source)
    {
        struct table  *result = NULL, *temp;
        size_t         size = 0;
        size_t         used = 0, n;
        int            err = 0;
    
        /* Read loop */
        while (1) {
    
            if (used + MAX_ITEMS_PER_READ > size) {
                /* Array size growth policy.
                 * Some suggest doubling the size,
                 * or using a constant factor.
                 * Here, the minimum is
                 *     size = used + MAX_ITEMS_PER_READ;
                */
                const size_t  newsize = 2*MAX_ITEMS_PER_READ + used + used / 2;
    
                temp = realloc(result, sizeof (struct table) + 
                                       newsize * sizeof (result->item[0]));
                if (!temp) {
                    err = ENOMEM;
                    break;
                }
    
                result = temp;
                size = newsize;
            }
    
            /* Read a record to result->item[used],
             * or up to (size-used) records starting at result->item + used.
             * If there are no more records, break.
             * If an error occurs, set err = errno, and break.
             *
             * Increment used by the number of records read: */            
            used++;
        }
    
        if (err) {
            free(result); /* NOTE: free(NULL) is safe. */
            errno = err;
            return NULL;
        }
    
        if (!used) {
            free(result);
            errno = ENODATA; /* POSIX.1 error code, not C89/C99/C11 */
            return NULL;
        }
    
        /* Optional: optimize table size. */
        if (used < size) {
            /* We don't mind even if realloc were to fail here. */
            temp = realloc(result, sizeof (struct table) + 
                                   used * sizeof table->item[0]);
            if (temp) {
                result = temp;
                size = used;
            }
        }
    
        result->size = size;
        result->used = used;
    
        errno = 0; /* Not normally zeroed; just my style. */
        return result;
    }
    
    char * ptr = malloc(256);
    if (!ptr) {
        return 1;
    }
    
    char * tmpPTR = realloc(ptr, 512);
    if (!tmpPTR) {
        printf("Houston, we have a problem");
        // ptr is fine
    }
    else {
        ptr = tmpPTR;
    }
    
    // ptr is realloc()ed