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

时间:2021-03-02 19:58:51

I am currently learning C and have to program a "dynamic array".

我目前正在学习C并且必须编写一个“动态数组”。

In a header file provided to us, the struct DynArray is declared as

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

struct DynamicArray
{
    unsigned int size;
    unsigned int capacity;

    int *data;
};

I have already implemented most of the functions in the dyn_array program, which was provided with empty functions.
My difficutly lies with the function dn_append(DynamicArray *a, int elem). The only description I have been given is

我已经在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
// =====================================================================================

We have a makefile to compile this and a few test cases. In one of the test programs, a new DynArray is initialized and then a few values are appended:

我们有一个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;
}

It aborts with a segmentation fault.
My (faulty) implementation is as follows. The outer else-case is completely messed up, since the debugging drove me crazy. (Note that I explain the problematic line after the code sample.)

它会因分段错误而中止。我的(错误的)实现如下。外部的其他情况完全搞砸了,因为调试让我抓狂。 (请注意,我在代码示例后解释了有问题的行。)

    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;
} 

The problematic line is in the outer else-case, in the middle:

有问题的行在外部的其他情况下,在中间:

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

When I run the program, these lines print out

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

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

I don't even touch the capacity-component of the struct, but it sets it to 0, which completely f***s up the following program.

我甚至没有触摸结构的容量组件,但它将其设置为0,这完全可以解决以下程序。

After commenting the line int sizeN = a->size;, the capacity is left right as it should.
I need to read the size, one way or another.

在注释int sizeN = a-> size;之后,容量保持正确。我需要以这种或那种方式阅读尺寸。

So, why the hell does it change that component?

那么,为什么它会改变那个组件呢?


Some additional infos:

一些额外的信息:

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;
    }
}

2 个解决方案

#1


In your dn_new() you have:

在你的dn_new()中你有:

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

Here, array is a local variable; it will be out of scope after returning it. You should allocate memory on the heap for that:

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

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

And remember to free() this memory in your destructor function (dn_destroy()).

并记住在析构函数(dn_destroy())中释放()这个内存。

#2


It seems that you mix up how you interpret your sizes and capacities. You use them as if the count the number of elements but you allocate them (with realloc) as number of bytes. Change your code to the following:

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

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

#1


In your dn_new() you have:

在你的dn_new()中你有:

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

Here, array is a local variable; it will be out of scope after returning it. You should allocate memory on the heap for that:

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

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

And remember to free() this memory in your destructor function (dn_destroy()).

并记住在析构函数(dn_destroy())中释放()这个内存。

#2


It seems that you mix up how you interpret your sizes and capacities. You use them as if the count the number of elements but you allocate them (with realloc) as number of bytes. Change your code to the following:

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

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