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;
}
}
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()
).
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]));