复制结构的组件会删除同一结构的另一个组件

Copying component of struct deletes another component of the same struct

我目前正在学习 C 并且必须编写 "dynamic array"。

在提供给我们的头文件中,结构体 DynArray 声明为

struct DynamicArray
{
    unsigned int size;
    unsigned int capacity;

    int *data;
};

我已经实现了dyn_array程序中的大部分功能,提供的是空函数
我的困难在于函数 dn_append(DynamicArray *a, int elem)。我得到的唯一描述是

// =====================================================================================
//         Name:  dn_append
//  Description:  Append an element.
//
//   Parameters:  a - the array
//                elem - the new value
//      Returns:  non-zero, if the array was successfully extended
// =====================================================================================

我们有一个 makefile 来编译这个和一些测试用例。在其中一个测试程序中,初始化了一个新的 DynArray,然后附加了一些值:

int
main ( int argc, char *argv[] )
{
    DynamicArray *a1;
    int                     i;

    a1 = dn_new ( 5 );

    dn_append ( a1,  5 );
    dn_append ( a1,  7 );
    dn_append ( a1,  8 );
    dn_append ( a1, 11 );
    dn_append ( a1, 13 );
    dn_append ( a1, 15 );

    dn_set ( a1, 2, 9 );

    for ( i = 0; i < dn_size ( a1 ); i += 1 )
    {
        printf ( "%d\n", dn_get ( a1, i ) );
    }

    dn_destory ( a1 );

    return 0;
}

它因分段错误而中止。
我的(错误的)实现如下。外部 else-case 完全搞砸了,因为调试让我发疯。 (请注意,我在代码示例之后解释了有问题的行。)

    int
dn_append ( DynamicArray *a, int elem )
{
    printf("\n\nAppend:\n");
    if (a->size >= a->capacity) {
        printf("Array too small");
        int *dataPtr = realloc(a->data, 2*a->capacity);

        if (dataPtr != NULL) {
            a->capacity *= 2;
            a->data = dataPtr;
            a->data[a->size] = elem;
            a->size++;
        }
        else {
                return 0;
        }
    }
    else {
        int *dataPtr;
        dataPtr = a->data;

        printf("Size: %d, Capacity: %d\n", a->size, a->capacity);
        int sizeN = a->size;
        printf("Size: %d, Capacity: %d\n", a->size, a->capacity);

        //int offset = sizeN;
        int *temp;
        temp = dataPtr;// + offset;
        //dataPtr[offset] = elem;
        //printf("Data at %d is %d, should be %d\n", offset, *(a->data), elem);

        a->size++;
    }

    return 1;
} 

有问题的行在外面的 else-case 中,在中间:

    printf("Size: %d, Capacity: %d\n", a->size, a->capacity);
    int sizeN = a->size;
    printf("Size: %d, Capacity: %d\n", a->size, a->capacity);

当我运行程序时,这些行打印出来

Size: 0, Capacity: 5
Size: 0, Capacity: 0

我什至没有触及结构的 capacity-组件,但它把它设置为 0,这完全搞砸了下面的程序。

在注释行 int sizeN = a->size; 之后,capacity 应该是左右对齐的。
我需要以某种方式阅读 size

那么,到底为什么要更改该组件?


一些附加信息:

DynamicArray*
dn_new ( unsigned int capacity )
{
    if (capacity > 0) {
        int *dataPtr = malloc(capacity*sizeof(int));

        if (dataPtr != NULL) {
            struct DynamicArray array = { 0, capacity, dataPtr };
            return &array;
        }
        else {
            return NULL;
        }
    }
    else {
        return NULL;
    }
}

您似乎混淆了对尺寸和容量的理解。您使用它们就像计算元素的数量一样,但您将它们(使用 realloc)分配为字节数。将您的代码更改为以下内容:

int *dataPtr = realloc(a->data, 2*a->capacity*sizeof(a->data[0]));

在你的 dn_new() 你有:

if (dataPtr != NULL) {
    struct DynamicArray array = { 0, capacity, dataPtr };
    return &array;
}

这里,array是局部变量;返回后将超出范围。您应该为此在堆上分配内存:

struct DynamicArray *array = malloc(sizeof *array);
array->size = 0;
array->capacity = capacity;
array->data = dataPtr;
return array;

并且记得 free() 在你的析构函数中 dn_destroy() 这个内存。