【问题标题】:Strange realloc behaviour奇怪的重新分配行为
【发布时间】:2011-02-24 02:49:57
【问题描述】:

我正在开发一个数组结构只是为了好玩。 这种结构,由模板参数概括,在启动时预先分配给定数量的项目,然后,如果“忙碌”项目多于可用项目,函数将重新分配内部缓冲区。 测试代码是:

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

template <typename T> struct darray_t {
    size_t items;
    size_t busy;
    T     *data;
};

#define DARRAY_REALLOC_ITEMS_STEP 10

#define da_size(da) (da)->busy

template <typename T>
void da_init( darray_t<T> *da, size_t prealloc ){
    da->items = prealloc;
    da->busy  = 0;
    da->data  = (T *)malloc( sizeof(T) * prealloc );
}

template <typename T> T *da_next( darray_t<T> *da ){
    if( da->busy >= da->items ){
        da->data   = (T *)realloc( da->data, sizeof(T) * DARRAY_REALLOC_ITEMS_STEP );
        da->items += DARRAY_REALLOC_ITEMS_STEP;
    }
    return &da->data[ da->busy++ ];
}

int main(){
    darray_t<int> vi;
    int *n;

    da_init( &vi, 100 );

    for( int i = 0; i < 101; ++i ){
        n = da_next(&vi);
        *n = i;
    }

    for( int i = 0; i < da_size(&vi); ++i ){
        if( vi.data[i] != i ){
            printf( "!!! %d != %d\n", i, vi.data[i] );
        }
    }

    return 0;
}

如您所见,我在开始时预分配了 100 个整数指针,然后我一次用另外 10 个指针重新分配它们。 在主函数中,我执行一个 for 循环来检查项目的完整性,如果一个数组项目不是我所期望的,我打印它的值并且......你知道吗? 我有以下消息:

!!! 11 != 135121

事实上,索引 11 处的项目,应该是 '11',是 135121 !!! :S

如果我的代码不正确,您能告诉我吗?

谢谢

注意 我完全知道以这种方式混合 C 和 C++ 是丑陋,而且我也知道如果使用这种结构会搞砸,例如:

darray_t<std::string>

这只是对 int 指针的测试。

【问题讨论】:

  • 呃,C 和模板,多么丑陋的组合。 (如果我用std::string 实例化你的模板,你认为会发生什么?)
  • 这个结构并不意味着与类一起使用,显然在这种情况下我应该使用 new 运算符来分配(调用类 ctor)并且我不能使用 realloc。但我再说一遍,这只是对 int 指针的测试。
  • @sbi: C with templates 是 CUDA 的一个习惯用法……但realloc 不是很多。
  • 仅供参考,如果你增加一个常数因子,那么你的 append 函数平均会得到 O(n),而如果你把大小加倍,那么你的 append 会得到平均 O(1)功能。
  • @Mike:是的,但他在 cmets 中非常明确地说这“只是对 int 指针的测试”。

标签: c++ c memory arrays realloc


【解决方案1】:

realloc 不会自动增加内存——你必须这样做。例如:

da->data=(T*)realloc(da->data, sizeof(T)*(da->items+DARRAY_REALLOC_ITEMS_STEP));

(你应该处理 realloc 返回 NULL)

【讨论】:

    【解决方案2】:

    块的大小不正确:

    da->data   = (T *)realloc( da->data, sizeof(T) * DARRAY_REALLOC_ITEMS_STEP );
    

    整个块与增量一样大。试试

    da->busy + sizeof(T) * DARRAY_REALLOC_ITEMS_STEP
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      • 2014-03-14
      • 2023-03-27
      • 2016-05-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多