Copying a struct component removes another component of the same structure

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

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

struct DynamicArray
{
    unsigned int size;
    unsigned int capacity;

    int *data;
};

      

I've already implemented most of the functions in the dyn_array program, which was supplied with empty functions.
My tricky part is the dn_append (DynamicArray * a, int elem) function. The only description I was given is

// =====================================================================================
//         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 some test cases. One test program initializes a new DynArray and then adds some values:

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 (flawed) implementation is as follows. The outer else-case got completely messed up as debugging made me go crazy. (Note that I will explain the problematic line after the sample code.)

    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

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

      

I don't even touch the capacity

-component of the structure, but sets it to 0, which runs the following program entirely.

After commenting out the line int sizeN = a->size;

, it capacity

stays in order as it should.
I need to read it size

, anyway.

So why the hell is he changing this component?


Additional Information:

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

      

+3


source to share


2 answers


In dn_new()

you have:

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

      

Here array

is a local variable; after his return, he will be unavailable. You have to allocate memory on the heap for this:



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

      

And remember free()

this memory in your destructor function ( dn_destroy()

).

+3


source


You seem to be confusing how you interpret your size and capabilities. You use them as if you were counting the number of elements, but you allocated them (s realloc

) as the number of bytes. Change your code to the following:



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

      

+2


source







All Articles