c - Realloc不能动态地将1增长到超过一百万个元素



读取2列文本文件并将长int值存储到动态重新分配的数组中,当该数组增长到超过20万个内存重新分配时失败。

    long int load_list_unklen(long int (**ptr), FILE *infname)
    {   long int row =0;
        char buf[64];
        while (fgets (buf, sizeof(buf), infname)) {
            // M is defined to be = 2
            *ptr = (long int *)realloc(*ptr, M * row+1 * sizeof(ptr));
            if(!ptr) {
                perror("Out of memory");
                free(ptr);
                exit( 1); }
            sscanf(buf, "%ldt%ld", &(*ptr)[row*2],&(*ptr)[row*2+1]);
            row += 1;
        }
        if (ferror(infname)) {
            fprintf(stderr,"Oops, error reading stdinn");
            abort();
        }
        return  row;
    }

注意,buf得到一个字符串,其中有两个由制表符分隔的数字。当它试图加载一个超过200万行的文件时,代码失败了,行增量停止在221181左右,因此我想知道这是否有realloc阻塞的限制?我应该用不同的方式称呼realloc吗?

下面是我如何调用这个函数:
long int *act_nei = (long int *)malloc(M * sizeof (act_nei) );
const long int sz  = load_list_unklen(&act_nei, fp);

使用来自SO post的代码来realloc内存插槽,其中我的示例是用于大型输入文件。
Realloc和sscanf转换成函数Realloc和scanf

由于写入超出分配的空间而损坏了malloc环。缺少(),尺寸错误。试一试:

* ptr =(长int *) realloc (* ptr, M *(行+ 1)*运算符(* * ptr));

您对内存使用情况的计算非常错误。

首先,不要总是使用*ptr,而是使用一个局部变量,这样可以使您的工作更轻松。像

long f (int* *pptr...)
{
    int* ptr = *pptr;
    ...
    *pptr = ptr;
}

现在很明显你的sizeof (ptr)是错误的。这是一个完全不相关的int**的大小。您需要的是int类型的大小,在代码中是sizeof(**ptr),如果使用指针的局部变量,则是sizeof(* ptr)。

当然,事情是完全错误的:

M * row+1 * sizeof(ptr)

计算M*行,然后加上1*sizeof(ptr)。您没有分配足够的内存,因此您的应用程序很快就会崩溃。

从已经发布的关于sizeof()的不正确使用的评论中,我有一个更一般的评论。我将避免为您读取的每行重新分配缓冲区。

realloc的语义是这样的,它将返回请求大小的连续内存区域。在某些操作系统上,如果可能的话,这将扩展作为参数"就地"传递的缓冲区。在其他操作系统中,或者如果传递的缓冲区末尾没有可用空间,则会分配一个全新的缓冲区,并将原始缓冲区的内容复制到该缓冲区。如果您的内存特别碎片化,这可能会导致内部出现多个mallocsmemcpy

在这种情况下,典型的方法是分配一个比实际需要大的缓冲区,并通过一个整数变量在内部跟踪已经使用了多少缓冲区。每当内部缓冲区的空间用完时,就调用realloc添加另一块空白空间。一些实现添加了一个固定大小的块,其他的是当前块的两倍大小,这取决于你和各种考虑因素。

另一个问题可能是由于realloc返回连续内存。根据操作系统和系统特性的不同,您可能没有指定大小的连续内存的空闲区域,但是可能有多个较小大小的空闲区域。如果可能出现这种情况,就必须考虑是否真的需要一个连续的缓冲区。例如,仍然提供O(1)访问时间(尽管不如连续缓冲区快)的解决方案可能是创建第一个缓冲区,其中包含指向固定大小的的指针。在这种情况下,在连续情况下作为ptr[n]的地址将在新方案中变为ptr[n / PAGE_SIZE][n % PAGE_SIZE]

可以通过使用包含元素计数和缓冲区的包装器结构来避免传递指针到指针和返回元素计数的习惯用法。(调用者可以丢弃包装器,只在需要时使用缓冲区)

#define handle_error() do{ perror("malloc"); exit(EXIT_FAILURE); } while (0)
struct pairs {
        unsigned size;
        unsigned used;
        struct { long int x; long int y; } *data;
        };
struct pairs *readpairs(FILE *fp)
{
struct pairs *ret;
char *line[80];
ret = malloc (sizeof *ret);
if (!ret) { handle_error();}
ret->size = ret->used = 0;
ret->data = NULL;
while (fgets(line, sizeof line, fp)) {
        int rc;
      if (ret->used >= ret->size) { // resize needed
                void *newp;
                unsigned newsiz;
                newsiz = ret->size ? 2* ret->size : 8;
                newp = realloc(ret->data,  newsiz * sizeof *ret->data);
                if (!newp) { handle_error();}
                ret->data = newp;
                ret->size = newsiz;
                }
        rc = sscanf(line,"%ldt%ld"
                , &ret->data[ret->used].x
                , &ret->data[ret->used].y
                );
        if (rc != 2) { handle_error();}
        ret->used += 1;
        }
return ret;
}

相关内容

  • 没有找到相关文章

最新更新