Reallocating array causes "Aborted" error - c

I wrote the following struct for a vector:
typedef struct Vector_ Vector;
struct Vector_
{
int dim;
double* vector;
};
And I wrote a function to initialise a new instance of that struct:
Vector* newVector(int length){
int i = 0;
Vector* vec = malloc(sizeof(Vector));
assert(vec != NULL);
assert(length > 0);
vec->dim = length;
vec->vector = malloc((length+1)*sizeof(double));
assert(vec->vector != NULL);
for(i=0;i<=length+1;i++) vec->vector[i] = 0;
return vec;
}
This all works, but then I wrote a function to reallocate memory and change the length of the vector like this:
Vector* setVectorLength(Vector* vec, int length)
{
assert(vec->dim > 0);
int i = 0;
if(length > vec->dim)
{
vec->vector = realloc(vec->vector,(length+1)*sizeof(double));
assert(vec->vector != NULL);
for(i = vec->dim+1;i<=length;i++)
{
vec->vector[i] = 0;
}
}
else
{
vec->vector = realloc(vec->vector,length+1 * sizeof(double));
}
vec->dim = length;
return vec;
}
And I call it like this:
int main()
{
Vector* newvec = newVector(5);
setVectorLength(newvec,8);
}
For some reason, the line in the setVectorLength function where I reallocate the memory of the vector array causes the program to abort. If I comment out that section, everything works. Interestingly, I am able to write entries to the array even without reallocating it to a sufficiently high length, so for example, if I only initialise the vector struct and give it the length 5, then I can write values into the 7th or 8th spot of the vec->vector array, even though I never allocated that much memory to it. Any hints?

Related

Creating a vector results in memory leak in C

I am trying to create a vector in C, following is the struct declaration:
#define VECT_INITIAL_CAPACITY 4
typedef struct vect vect_t;
struct vect {
char **data; // data is an array of strings
unsigned int size;
unsigned int capacity;
};
I have a function that constructs a new empty vector, here is what I did:
vect_t *vect_new() {
vect_t *v = (vect_t*) malloc(sizeof(vect_t));
if (v == NULL) {
return NULL;
}
// Allocate memory for data
v->data = (char**) malloc(VECT_INITIAL_CAPACITY * sizeof(char*));
if (v->data == NULL) {
return NULL;
}
for (int i = 0; i < VECT_INITIAL_CAPACITY; i++) {
v->data[i] = NULL;
}
// Initialize fields
v->size = 0;
v->capacity = VECT_INITIAL_CAPACITY;
return v;
}
Valgrind tells me that the line v->data = (char**) malloc(VECT_INITIAL_CAPACITY * sizeof(char*)); caused memory leak. But I'm not sure how to fix this. Can anyone point out what caused the memory leaks?
Edit: Added my cleanup code below:
/** Free all the memories of the vector. */
void vect_delete(vect_t *v) {
// Delete data first
for (int i = 0; i < v->size; i++) {
free(v->data[i]);
}
// Delete the vector
free(v);
}
/** Delete the vector, freeing all memory it occupies. */
void vect_delete(vect_t *v)
{
if(v)
{
// Delete data first
if(v -> data)
for (size_t i = 0; i < v->capacity; i++) //not v->size
{
free(v->data[i]);
}
free(v -> data); //missing
// Delete the vector
free(v);
}
}
Some remarks:
Use the correct type for sizes and indexes (size_t) not int or unsigned
Use objects instead of types in sizeofs. vect_t *v = malloc(sizeof(*v));
Do not cast the results of void * functions like malloc. If the code does not compile, then you use the wrong compiler (C++ one) to compile C code.
In addition to #0___________ good answer,
if (v->data == NULL) { return NULL; } also leaks.
Use if (v->data == NULL) { free(v); return NULL; }.

allocate a 3d array that contains strings

I wrote a 'class' that can store strings (2d array/matrix). This works fine, but now I need a way to store that matrix. So I need to calloc the 3tensor but i am not sure how to do it beyond the matrice allocation.
My 2d array looks like this: \
#pragma once
#include <stdlib.h>
#include <stdint.h> /* uints */
#include <string.h> /* char */
/* struct that holds data about the matrix, so it can be resized when needed */
struct Arr {
char** cArr;
unsigned int currentSize, maxSize;
};
/* initial allocation function that is used when a array needs te be calloced at first */
uint8_t initialAlloc(struct Arr* arr);
/* reallocate the array to a hardcoded size */
uint8_t reallocArr(struct Arr* arr);
/* add an element to the array in arr */
void addToArr(struct Arr* arr, char* element);
#include "arr.h"
uint8_t initialAlloc(struct Arr* arr) {
arr->currentSize = 0;
arr->maxSize = 2;
arr->cArr = calloc(2, sizeof(char*));
if (!arr->cArr) {
return 0;
}
for (uint8_t x = 0; x < arr->maxSize; ++x) {
arr->cArr[x] = calloc(600, sizeof(char));
if (!arr->cArr[x]) {
return 0;
}
}
return 1;
}
void addToArr(struct Arr* arr, char* element) {
if (arr->currentSize == arr->maxSize) {
if (!reallocArr(arr)) {
/* if the memory allocation fails something is bad wrong */
exit(1);
}
}
strncpy(arr->cArr[arr->currentSize], element, strlen(element));
++arr->currentSize;
}
uint8_t reallocArr(struct Arr* arr) {
uint16_t resizeTo = arr->maxSize * 2;
arr->cArr = realloc(arr->cArr, resizeTo * sizeof(char*));
if (!arr->cArr) {
return 0;
}
for (uint16_t x = arr->currentSize; x < resizeTo; ++x) {
arr->cArr[x] = calloc(600, sizeof(char));
if (!arr->cArr[x]) {
return 0;
}
}
arr->maxSize = arr->maxSize * 2;
return 1;
}
I want to use the Arr struct inside the 3tensor.
#pragma once
#include <stdlib.h> /* basic functions */
#include <stdint.h> /* uint */
/* user includes */
#include "characterArr.h"
/* user includes */
struct Tensor {
char*** mArr;
unsigned int currentSize, maxSize;
};
uint8_t initialAllocTensor(struct Tensor* tensor);
uint8_t reallocTensor(struct Tensor* tensor);
void addToTensor(struct Tensor* tensor, struct Arr* arr);
/* user includes */
#include "tensor.h"
/* user includes */
/* initial allocation function that is used when a array needs te be calloced at first */
uint8_t initialAllocTensor(struct Tensor* tensor) {
tensor->currentSize = 0;
tensor->maxSize = 2;
tensor->mArr = calloc(2, sizeof(struct *Arr));
if (!tensor->mArr) {
return 0;
}
for (uint8_t x = 0; x < arr->maxSize; ++x) {
arr->cArr[x] = calloc(600, sizeof(char));
if (!arr->cArr[x]) {
return 0;
}
}
return 1;
}
After I allocate the memory that will contain the pointers to the Arr struct, I get lost. The reason is, I need the information in the Arr struct for later use, so why would I recopy all the data from the Arr struct that i already have into the newly created 3Tensor. Could I just store a pointer to the Arr struct in the Tensor then be done? If i do this, would I be able to access the Arr struct just fine? Since I malloced this, I wouldn't need to worry about the memory getting taken when it goes out of scope.

in c, value is changing from the end of a function to outside the function after function call

In line 77 v->size is 0 while in line 186 v-size is 2. I dont understand why this is so because line 186 is at the very end of the function definition of void _setCapacityDynArr(struct DynArr *v, int newCap)(in line 140) and line 77 is right after the call to the function. Somehow between the end of the function and the next line after the function call the value has changed. I thought because v is a pointer it should retain the value. If someone could please tell me why the value is changing it would be greatly appreciated. I've run out of ideas and have no idea what to do.
http://pastebin.com/tWR6w8rG
/*
* File: main.c
* Author: user1
*
* Created on April 7, 2015, 3:57 PM
*/
#include <stdio.h>
#include <stdlib.h>
/*
* File: main.c
* Author: user1
*
* Created on April 7, 2015, 3:57 PM
*/
/*
*
*/
# ifndef TYPE
# define TYPE int
# endif
struct DynArr
{
TYPE *data;
int size;
int capacity;
};
/* pointer to the data array */
/* Number of elements in the array */
/* capacity ofthe array */
void initDynArr(struct DynArr *v, int capacity)
{
v->data = malloc(sizeof(TYPE) * capacity);
//assert(v->data != 0);
v->size = 0;
v->capacity = capacity;
}
void freeDynArr(struct DynArr *v)
{
if(v->data != 0)
{
free(v->data); /* free the space on the heap */
v->data = 0;
/* make it point to null */
}
v->size = 0;
v->capacity = 0;
}
int sizeDynArr( struct DynArr *v)
{
return v->size;
}
/*
void addDynArr(struct DynArr *v, TYPE val)
{
// Check to see if a resize is necessary
if(v->size == v->capacity)
_setCapacityDynArr(v, 2 * v->capacity);
v->data[v->size] = val;
v->size++;
}
*/
void addDynArr(struct DynArr *v, TYPE val)
{
// Check to see if a resize is necessary
if(v->size >= v->capacity)
{
_setCapacityDynArr(v, 2 * v->capacity);
printf(">>>%d",v->size); //<<<<<<<<<<<<<<<<<<<<v->size = 0
v->data[v->size] = val;
v->size++;
printf("setcapacity: size is: %d capacity is: %d value is %d value in array is: %d\n", v->size, v->capacity, val, v->data[v->size-1]);
}
else
{
v->data[v->size] = val;
v->size++;
printf("not setcapacity: size is: %d capacity is: %d value is %d value in array is: %d\n", v->size, v->capacity, val, v->data[v->size-1]);
}
//printf("%d\n", v->capacity);
}
void removeDynArray(struct DynArr *b, TYPE v)
{
for(int i = 0; i < b->size; i++)
{
if(b->data[i] == v)
{
while(i < (b->size))
{
b->data[i] = b->data[i+1];
i++;
}
break;
}
}
b->size--;
}
void print(struct DynArr *v)
{
for(int i = 0; i < v->size; i++)
{
printf("%d\n", v->data[i]);
}
}
//do this
void _setCapacityDynArr(struct DynArr *v, int newCap)
{
struct DynArr* temp;
temp = v;
///print(temp);
//struct DynArr v;
v = malloc(sizeof(struct DynArr));
v->data = malloc(sizeof(TYPE) * newCap);
v->capacity = newCap;
v->size = 0; //temp size is also being set
for (int i = 0 ; i < temp->size; i++)
{
v->data[i] = temp->data[i];
v->size++;
}
free(temp->data);
temp->size = 0;
temp->capacity = 0;
temp = 0;
printf(">!>>%d",v->size); //////////<<<<<<<<<<<<<<<<<<<<<<<<v->size = 2
}
int main(int argc, char** argv)
{
struct DynArr a;
initDynArr(&a, 2);
addDynArr(&a, 5);
addDynArr(&a, 7);
addDynArr(&a, 8);
//printf("%d\n", a.size);
//print(&a);
// printf ("%d\n",a.data[2]);
return (EXIT_SUCCESS);
}
Your _setCapacityDynArr function is written in a rather nonsensical fashion. All functions in this "API" receive a pointer v (or, sometimes, b) to an existing struct DynArr object, which they work with. They can manipulate the fields of *v object. They can allocate/deallocate/reallocate the actual array v->data. But they never allocate/deallocate the *v object itself. Object *v is passed from the outside and managed by the outside code.
But your _setCapacityDynArr function attempts to do something completely and drastically different. It begins with
temp = v;
v = malloc(sizeof(struct DynArr));
...
free(temp);
That is already incorrect. This is completely unacceptable. You are not allowed to allocate/deallocate *v object itself.
In any case, changing the value of v inside the function make no sense simply because v is passed to _setCapacityDynArr by value. The outside code will not see these changes anyway.
This latter detail is what makes your code to output allegedly "changing" value of v->size - you are simply outputing two completely different v->size values and one of them actually belongs to deallocated memory. In line 77 you are printing v->size value stored in "dead" memory already deallocated by free(temp) call inside _setCapacityDynArr.
Don't try to acclocate/deallocate *v object inside your _setCapacityDynArr. Where did you get that idea? Just reallocate v->data and change the other firelds accordingly. But don't attempt to change the value of v itself.

C: adding element to dynamically allocated array

I've tried to search out a solution via Google: I couldn't find anything that helped; it even seemed as if I was doing this correctly. The only pages I could find regarding sending my dynamically allocated array through a function dealt with the array being inside a struct, which is scalar of course, so behaves differently. I don't want to use a struct right now -- I'm trying to learn about DAM and working with pointers and functions.
That said, I'm sure it's very elementary, but I'm stuck. The code compiles, but it freezes up when I run the executable. (I'm using minGW gcc, if that matters. And I'm not clear at all, right now, on how to use gdb.)
Here's the code (eventually, I want the entire code to be an ArrayList-like data structure):
#include <stdio.h>
#include <stdlib.h>
void add( int element, int *vector);
void display_vector( int *vector );
void initialize_vector( int *vector );
int elements = 0;
int size = 10;
int main(void)
{
int *vector = 0;
initialize_vector(vector);
add(1, vector);
//add(2, vector);
//add(3, vector);
//add(4, vector);
//add(5, vector);
//add(6, vector);
//add(7, vector);
//add(8, vector);
//add(9, vector);
//add(10, vector);
//add(11, vector);
display_vector(vector);
return 0;
}
void add( int element, int *vector)
{
vector[elements++] = element;
return;
}
void display_vector( int *vector )
{
int i;
for( i = 0; i < elements; i++)
{
printf("%2d\t", vector[i]);
if( (i + 1) % 5 == 0 )
printf("\n");
}
printf("\n");
return;
}
void initialize_vector( int *vector )
{
vector = (int *)malloc(sizeof(int) * size);
}
Edited to make a little bit more clear.
The problem is your init routine is working with a copy of "vector" and is malloc'ing into that copy rather than the original vector pointer. You loose the pointer to the memory block on the return from the initialize.
Change parameter for vector to a handle (pointer to pointer) in this function
void initialize_vector( int **vector )
{
*vector = (int *)malloc(sizeof(int) * size);
}
Then change the call to init to this
initialize_vector(&vector);
I didn't compile this, but it should fix the code.
In C, function arguments are passed by value, which means there is a local copy for every arguments you passed to a function, if you change an argument in a function, you only change the local copy of that argument. So if you want to change the value of an argument in a function, you need to pass its address to that function, derefer that address and assign to the result in that function.
Enough for the theory, here is how to fix your code:
void initialize_vector( int **vector );
initialize_vector(&vector);
void initialize_vector( int **vector )
{
*vector = (int *)malloc(sizeof(int) * size);
}
In addition of other replies, I would suggest another approach.
Assuming at least C99 compliant compiler, I would rather suggest to keep the allocated size in a member of a structure ending with a flexible array member (see also this) like:
typedef struct vector_st {
unsigned count; // used length
unsigned size; // allocated size, always >= length
int vectarr[];
} Vector;
Then you would construct such a vector with
Vector* make_vector (unsigned size) {
Vector* v = malloc(sizeof(Vector)+size*sizeof(int));
if (!v) { perror("malloc vector"); exit (EXIT_FAILURE); };
memset (v->vectarr, 0, size*sizeof(int));
v->count = 0;
v->size = size;
}
To add an element into a vector, returning the original vector or a grown one:
Vector* append_vector (Vector*vec, int elem) {
assert (vec != NULL);
unsigned oldcount = vec->count;
if (oldcount < vec->size) {
vec->vectarr[vec->count++] = elem;
return vec;
} else {
unsigned newsize = ((4*oldcount/3)|7) + 1;
Vector* oldvec = vec;
vec = malloc(sizeof(Vector)+newsize*sizeof(int));
if (!vec) { perror("vector grow"); exit(EXIT_FAILURE); };
memcpy (vec->vectarr, oldvec->vectarr, oldcount*sizeof(int));
memset (vec->vectarr + oldcount, 0,
(newsize-oldcount) * sizeof(int));
vec->vectarr[oldcount] = elem;
vec->count = oldcount+1;
vec->size = newsize;
free (oldvec);
return vec;
}
}
and you could code:
Vector* myvec = make_vector(100);
myvec = append_vector(myvec, 35);
myvec = append_vector(myvec, 17);
for (int i=0; i<150; i++)
myvec = append_vector(myvec, i*2);
To release such a vector, just use free(myvec);
If you really don't want to use any struct you should keep in separate variables the used length of your vector, the allocated size of your vector, the pointer to your dynamically allocated array:
unsigned used_count; // useful "length"
unsigned allocated_size; // allocated size, always not less than used_count
int *dynamic_array; // the pointer to the dynamically allocated array
If you want to be able to manage several vectors, then either pack together the above useful length, allocated size and dynamic array into some struct dynamic_array_st (whose pointer you would pass to appropriate routines like make_dynamic_vector(struct dynamic_array_st*), append_dynamic_vector(struct dynamic_array_st*, int), etc ....) or else pass them as three separate formals to similar routines, and then you'll need to pass their address because the routines would change them, e.g. create_dynamic_vector(unsigned *countptr, unsigned *sizeptr, int**vectarrptr) that you would invoke as create_dynamic_vector(&mycount, &mysize, &myvectarr); etc.
I do think that a flexible array member is still the cleanest approach.

dynamic array and pointer in C

I'm a beginner in C and programming. I would like to ask some questions on dynamic array and pointer in C.
I am trying to create a dynamic array and increase its capacity, but I can't get my code working. I believe something is wrong in my setCapacityDynArr function.
Can someone give me some help?
Thanks!
struct DynArr {
TYPE *data; /* pointer to the data array */
int size; /* Number of elements in the array */
int capacity; /* capacity ofthe array */
};
void initDynArr(struct DynArr *v, int capacity) {
v->data = malloc(sizeof(TYPE) * capacity);
assert(v->data != 0);
v->size = 0;
v->capacity = capacity;
}
void freeDynArr(struct DynArr *v) {
if (v->data != 0) {
free(v->data); /* free the space on the heap */
v->data = 0; /* make it point to null */
}
v->size = 0;
v->capacity = 0;
}
int sizeDynArr(struct DynArr *v) {
return v->size;
}
void addDynArr(struct DynArr *v, TYPE val) {
/* Check to see if a resize is necessary */
if (v->size >= v->capacity) {
_setCapacityDynArr(v, 2 * v->capacity);
}
v->data[v->size] = val;
v->size++;
}
void _setCapacityDynArr(struct DynArr *v, int newCap) {
//create a new array
struct DynArr *new_v;
assert(newCap > 0);
new_v = malloc(newCap * sizeof(struct DynArr));
assert(new_v != 0);
initDynArr(new_v, newCap);
//copy old values into the new array
for (int i = 0; i < new_v->capacity; i++) {
new_v->data[i] = v->data[i];
}
//free the old memory
freeDynArr(v);
//pointer is changed to reference the new array
v = new_v;
}
int main(int argc, const char * argv[]) {
//Initialize an array
struct DynArr myArray;
initDynArr(&myArray, 5);
printf("size = 0, return: %d\n", myArray.size);
printf("capacity = 5, return: %d\n", myArray.capacity);
//Add value to the array
addDynArr(&myArray, 10);
addDynArr(&myArray, 11);
addDynArr(&myArray, 12);
addDynArr(&myArray, 13);
addDynArr(&myArray, 14);
addDynArr(&myArray, 15);
for (int i = 0; i < myArray.size; i++) {
printf("myArray value - return: %d\n", myArray.data[i]);
}
return 0;
}
//pointer is changed to reference the new array
v = new_v;
This is your problem, a classic mistake in C. In fact the function changes its own copy of the pointer, the caller never sees the change. The problem is amply described by this C FAQ.
I suggest a different approach. There's no reason to make a new v: you simply want more storage associated with it. So instead of actually changing v, you'll probably want to just call realloc on the storage: v->DATA.
You might get away with something like:
tmp = realloc(v->data, newCap * sizeof *v->data);
if (!tmp)
error;
v->data = tmp;
And this way you don't need to copy the elements either: realloc takes care of that.
//pointer is changed to reference the new array
v = new_v;
Your original pointer outside the function is not changed, since you passed the value of the pointer not the address of it here:
void _setCapacityDynArr(struct DynArr *v, int newCap)
{
Yes it's an error in _setCapacityDynArr. It's an error because you declare an DynArr structure on the stack, then you try to free it and assign a new pointer to it. That will not work, as items allocated on the stack can't be freed.
What you want to do is to reallocate only the actual data, not the whole structure. For this you should use the realloc function.
There are other problems with the function as well, like you assigning to the pointer. This pointer is a local variable so when the function returns all changes to it will be lost.

Resources