Simulating a List with array - c

Good morning!
I must handle a struct array (global variable) that simulates a list. In practice, every time I call a method, I have to increase the size of the array 1 and insert it into the new struct.
Since the array size is static, my idea is to use pointers like this:
The struct array is declared as a pointer to a second struct array.
Each time I call the increaseSize () method, the content of the old array is copied to a new n + 1 array.
The global array pointer is updated to point to a new array
In theory, the solution seems easy ... but I'm a noob of c. Where is that wrong?
struct task {
char title[50];
int execution;
int priority;
};
struct task tasks = *p;
int main() {
//he will call the increaseSize() somewhere...
}
void increaseSize(){
int dimension = (sizeof(*p) / sizeof(struct task));
struct task newTasks[dimension+1];
for(int i=0; i<dimension; i++){
newTasks[i] = *(p+i);
}
free(&p);
p = newTasks;
}

You mix up quite a lot here!
int dimension = (sizeof(*p) / sizeof(struct task));
p is a pointer, *p points to a struct task, so sizeof(*p) will be equal to sizeof(struct task), and dimension always will be 1...
You cannot use sizeof in this situation. You will have to store the size (number of elements) in a separate variable.
struct task newTasks[dimension+1];
This will create a new array, yes – but with scope local to the current function (so normally, it is allocated on the stack). This means that the array will be cleaned up again as soon as you leave your function.
What you need is creating the array on the heap. You need to use malloc function for (or calloc or realloc).
Additionally, I recomment not increasing the array by 1, but rather duplicating its size. You need to store the number of elements contained in then, too, though.
Putting all together:
struct task* p;
size_t count;
size_t capacity;
void initialize()
{
count = 0;
capacity = 16;
p = (struct task*) malloc(capacity * sizeof(struct task));
if(!p)
// malloc failed, appropriate error handling!
}
void increase()
{
size_t c = capacity * 2;
// realloc is very convenient here:
// if allocation is successful, it copies the old values
// to the new location and frees the old memory, so nothing
// so nothing to worry about except for allocation failure
struct task* pp = realloc(p, c * sizeof(struct task));
if(pp)
{
p = pp;
capacity = c;
}
// else: apprpriate error handling
}
Finally, as completion:
void push_back(struct task t)
{
if(count == capacity)
increase();
p[count++] = t;
}
Removing elements is left to you – you'd have to copy the subsequent elements all to one position less and then decrease count.

Related

How to correctly allocate memory to a dynamic array of integers stored in a struct?

I have a function that sets values to a struct:
My struct:
struct entry {
char key[MAX_KEY];
int* values;
size_t length;
entry* next;
entry* prev;
};
My function:
// Sets entry values
void command_set(char **commands, int arg_num) {
struct entry e;
e.length++;
strcpy(e.key, commands[1]);
for (int i = 2; i < arg_num; i++) {
e.values[i - 2] = atoi(commands[i]);
}
}
where:
**commands: is a array of strings
arg_num: is how many strings are in the array
key: is the name of the entry
values: are integer values store in the entry
I run the code and I get a segmentation fault 11. I have narrowed it down to the line:
e.values[i -2] = atoi(commands[i]);
I assume that I have to use malloc to allocate memory as I don't appear to have gone out of bounds with my loop. I have tried to understand the correct way to allocate memory however I can't seem to get the syntax correct for allocating sizeof(int) to a dynamic array of integers.
I have tried:
e.values[i - 2] = malloc(sizeof(int));
and
e.values[i - 2] = (int) malloc(sizeof(int));
and
e.values[i - 2] = malloc(sizeof(int *));
However I get the error:
incompatible pointer to integer conversion assigning
to 'int' from 'void *' [-Werror,-Wint-conversion]
You must allocate the whole array:
e.values = malloc(sizeof(int) * (arg_num - 2))
Important: Remember to call free when you're done with the memory or you will have a memory leak.
You have another problem though, unrelated to the one you're asking about.
You do
struct entry e;
e.length++;
When the structure object e is defined, it is uninitialized, all its members will have an indeterminate value. Using such uninitialized data in any way except to initialize it will lead to undefined behavior. And you do use such uninitialized values when you do e.length++.
That increase simply doesn't make any sense in the code as you show it. On the other hand, that function doesn't make a lot of sense anyway since the variable e and all its data will simply "disappear" when the function returns. So I can only assume that it's not the complete function you show us.
To initialize the structure to all zeroes, simply do
struct entry e = { 0 };
as your struct is as follows
struct entry {
char key[MAX_KEY];
int* values;
size_t length;
entry* next;
entry* prev;
};
then you should allocate memory to it as
e.values =(int *)malloc(arg_num*sizeof(int));
like if you have 10 values then you are allocating 10*4 values to it.
and invoke free on it
free(e.values)
when the e or e.values is no more useful. for more information you can see here
Modify the function as below.
void command_set(char **commands, int arg_num) {
struct entry e;
e.length++;
strcpy(e.key, commands[1]);
//here is the memory allocation
e.values = malloc(arg_num-1 * sizeof(int));
for (int i = 0; i < arg_num-1; i++) {
e.values[i] = atoi(commands[i+1]);
}
}

C create array of struct using constructor function

I have a C struct:
typedef struct {
Dataset *datasets;
int nDatasets;
char *group_name;
enum groupType type;
} DatasetGroup;
It has a constructor function like this:
DatasetGroup * new_DatasetGroup(char *group_name, enum groupType type, enum returnCode *ret)
{
DatasetGroup *dg;
dg = (DatasetGroup *) malloc(sizeof(DatasetGroup));
if (dg == NULL)
{
*ret = EMEMORY_ERROR;
}
// Allocate space for a few datasets
dg->datasets = malloc(sizeof(Dataset) * INCREMENT);
if (dg->datasets == NULL)
{
*ret = EMEMORY_ERROR;
}
dg->group_name= malloc(sizeof(char) * strlen(group_name));
strcpy(dg->group_name, group_name);
dg->type = type;
groupCount++;
return dg;
}
I want to dynamically create an array of these structs. Whats the best way to do this?
So far I have something like:
DatasetGroup * make_array(){
DatasetGroup *dg_array;
// Allocate space for a few groups
dg_array = (DatasetGroup *) malloc(sizeof(DatasetGroup) * INCREMENT);
return dg_array;
}
void add_group_to_array(DatasetGroup *dg_array, ...){
// Add a datasetgroup
DatasetGroup *dg = new_DatasetGroup(...);
// groupCount - 1 as the count is incremented when the group is created, so will always be one ahead of the array index we want to assign to
dg_array[groupCount - 1] = dg;
if (groupCount % INCREMENT == 0)
{
//Grow the array
dg_array = realloc(dg_array, sizeof(DatasetGroup) * (groupCount + INCREMENT));
}
}
But this doesnt seem right....
any ideas?
A few suggestions:
You have groupCount being incremented by the constructor function of the struct. This means you can only have one array of the struct that uses your array function. I would recommend having the array be responsible for managing the count.
To that affect if you want to have a managed array I would create a struct for that and have it keep both the pointer to the array,the number of objects and the size of the array (e.g. the maximum number of structs it can currently hold)
If you keep proper track of how many elements you have and the size of the array you can replace groupCount % INCREMENT == 0 with something like groupCount == arraySize which is a lot more intuitive in my opinion.
You can avoid the second malloc in the constructor all together by having the array be an array of the elements instead of an array of pointers. The constructor than then just initialize the struct members instead of allocating memory. If you are doing this a lot you will be avoiding a lot of memory fragmentation.
Finally, while this depends on your application, I usually recommend when you realloc do not increase by a constant but instead of by a multiple of the current array size. If say you double the array size you only have to do log_2 n number of reallocs with n being the final array size and you waste at most half of memory (memory is generally cheap, like I said it depends on the application). If that is wasting to much memory you can do say 1.5. If you want a more detailed explanation of this I recommend this Joel on Software article, the part about realloc is about 2/3 down.
Update:
A few others things:
dg = (DatasetGroup *) malloc(sizeof(DatasetGroup));
if (dg == NULL)
{
ret = EMEMORY_ERROR;
}
// Allocate space for a few datasets
dg->datasets = malloc(sizeof(Dataset) * INCREMENT);
As previously pointed out is very bad as you will us dg even if it is NULL. You probably want to exit right after detecting the error.
Furthermore you are setting ret but ret is passed by value so it will not be changed for the caller if the callee changes it. Instead you probably want to pass a pointer and dereference it.
Update 2: Can I give an example, sure, quick not so much ;-D.
Consider the following code (I apologize if there are any mistakes, still half asleep):
#include <stdio.h>
#include <stdlib.h>
#define LESS_MALLOCS
#define MAX_COUNT 100000000
typedef struct _foo_t
{
int bar1;
int bar2;
} foo_t;
void foo_init(foo_t *foo, int bar1, int bar2)
{
foo->bar1 = bar1;
foo->bar2 = bar2;
}
foo_t* new_foo(int bar1, int bar2)
{
foo_t *foo = malloc(sizeof(foo_t));
if(foo == NULL) {
return NULL;
}
foo->bar1 = bar1;
foo->bar2 = bar2;
return foo;
}
typedef struct _foo_array_t
{
#ifdef LESS_MALLOCS
foo_t *array;
#else
foo_t **array;
#endif
int count;
int length;
} foo_array_t;
void foo_array_init(foo_array_t* foo_array, int size) {
foo_array->count = 0;
#ifdef LESS_MALLOCS
foo_array->array = malloc(sizeof(foo_t) * size);
#else
foo_array->array = malloc(sizeof(foo_t*) * size);
#endif
foo_array->length = size;
}
int foo_array_add(foo_array_t* foo_array, int bar1, int bar2)
{
if(foo_array->count == foo_array->length) {
#ifdef LESS_MALLOCS
size_t new_size = sizeof(foo_t) * foo_array->length * 2;
#else
size_t new_size = sizeof(foo_t*) * foo_array->length * 2;
#endif
void* tmp = realloc(foo_array->array, new_size);
if(tmp == NULL) {
return -1;
}
foo_array->array = tmp;
foo_array->length *= 2;
}
#ifdef LESS_MALLOCS
foo_init(&(foo_array->array[foo_array->count++]), bar1, bar2);
#else
foo_array->array[foo_array->count] = new_foo(bar1, bar2);
if(foo_array->array[foo_array->count] == NULL) {
return -1;
}
foo_array->count++;
#endif
return foo_array->count;
}
int main()
{
int i;
foo_array_t foo_array;
foo_array_init(&foo_array, 20);
for(i = 0; i < MAX_COUNT; i++) {
if(foo_array_add(&foo_array, i, i+1) != (i+1)) {
fprintf(stderr, "Failed to add element %d\n", i);
return EXIT_FAILURE;
}
}
printf("Added all elements\n");
return EXIT_SUCCESS;
}
There is a struct (foo_t) with two members (bar1 and bar2) and another struct that is an array wrapper (foo_array_t). foo_array_t keeps track of the current size of the array and the number of elements in the array. It has an add element function (foo_array_add). Note that there is a foo_init and a new_foo, foo_init takes a pointer to a foo_t and new_foo does not and instead returns a pointer. So foo_init assumes the memory has been allocated in some way, heap, stack or whatever doesn't matter, while new_foo will allocate memory from the heap. There is also a preprocess macro called LESS_MALLOCS. This changes the definition of the array member of foo_array_t, the size of the initial array allocation, the size during reallocation and whether foo_init or new_foo is used. The array and its size have to change to reflect whether a pointer or the actually element is in the array. With LESS_MACRO defined the code is following my suggestion for number 4, when not, it is more similar to your code. Finally, main contains a simple micro-benchmark. The results are the following:
[missimer#asus-laptop tmp]$ gcc temp.c # Compile with LESS_MACROS defined
[missimer#asus-laptop tmp]$ time ./a.out
Added all elements
real 0m1.747s
user 0m1.384s
sys 0m0.357s
[missimer#asus-laptop tmp]$ gcc temp.c #Compile with LESS_MACROS not defined
[missimer#asus-laptop tmp]$ time ./a.out
Added all elements
real 0m9.360s
user 0m4.804s
sys 0m1.968s
Not that time is the best way to measure a benchmark but in this case I think the results speak for themselves. Also, when you allocate an array of elements instead of an array of pointers and then allocate the elements separately you reduce the number of places you have to check for errors. Of course everything has trade-offs, if for example the struct was very large and you wanted to move elements around in the array you would be doing a lot of memcpy-ing as opposed to just moving a pointer around in your approach.
Also, I would recommend against this:
dg_array = realloc(dg_array, sizeof(DatasetGroup) * (groupCount + INCREMENT));
As you lose the value of the original pointer if realloc fails and returns NULL. Also like your previous ret, you should pass a pointer instead of the value as you are not changing the value to the caller, just the callee which then exits so it has no real affect. Finally, I noticed you changed your function definition to have a pointer to ret but you need to dereference that pointer when you use it, you should be getting compiler warnings (perhaps even errors) when you do try what you currently have.
You could do two things, either you dynamically create an array of struct pointers, then call your new function to create N datagroups, or you could dynamically request memory for N structures at once, this would mean your N structures would be contiguously allocated.
Datagroup **parry = malloc(sizeof(datagroup *) * N)
for (int i = 0; i < N; i++){
parry[i] = //yourconstructor
}
Or
//allocate N empty structures
Datagroup *contarr = calloc(N, sizeof(Datagroup))
The second method might need a different initialization routine than your constructor, as the memory is already allocated

Freeing array of struct

I've done some research and couldn't find any answer to my problem.
I'm having problems with freeing my struct.
This is how i create my struct:
struct Structure * newStructure(int N)
{
struct Structure * structure;
int i;
structure = (struct Structure * ) malloc(N * sizeof(struct Structure));
for (i = 0; i < N; i++)
{
structure[i].i_Number = (int * ) malloc(sizeof(int));
structure[i].c_Char = (char * ) malloc(sizeof(char));
structure[i].c_Char[0] = '\0';
structure[i].d_Float = (double * ) malloc(sizeof(double));
}
return structure;
}
Everything works to this point. Later I fill every variable with random values so that they are not empty.
I call my freeMemory function like this freeMemory(structure, amountOfStructures);
And here is freeMemory function itself:
void freeMemory (struct Structure* structure, int N)
{
int i;
for( i=0 ; i<N ; i++ )
{
if (structure[i].i_Number!=NULL) free(structure[i].i_Number);
if (structure[i].c_Char!=NULL) free(structure[i].c_Char);
if (structure[i].d_Float!=NULL) free(structure[i].d_Float);
}
free(structure);
}
The free(structure) part works fine. But there are problems with the for loop and I have no idea what I'm doing wrong here.
#EDIT
I'm adding my struct declaration:
struct Structure{
int *i_Number;
char *c_Char;
double *d_Float;
};
#EDIT2
That's the function that initializes struct:
struct Structure* randomizing (int N)
{
struct Structure* structure = newStructure(N); int i;
srand(time(NULL));
for (i = 0; i < N; i++)
{
int _i; char _c; double _d;
_i = rand()%1000000;
_c = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" [rand () % 26];
_d = 0;
setStructureNumber(structure, i,(int*) _i);
setStructureChar(structure, i, (char*) _c);
setStructureDouble(structure, i, &_d);
// I'VE COMMENTED OUT THE MUTATORS ABOVE AND THE ERROR DOES NOT SHOW ANYMORE, SO THERES SOMETHING WRONG WITH THEM
}
return structure;
}
And im calling it like this:
struct Structure* structure;
structure = randomizing(amountOfStructures);
The mutators used:
// Mutators
void setStructureNumber (struct Structure* structure, int p, int* num)
{
if (structure[p].i_Number != NULL) free(structure[p].i_Number);
structure[p].i_Number = (int*) malloc (sizeof(int));
structure[p].i_Number = num;
}
void setStructureChar (struct Structure* structure, int p, char* str)
{
if (structure[p].c_Char != NULL) free(structure[p].c_Char);
structure[p].c_Char = (char*) malloc (sizeof(char));
structure[p].c_Char = str;
}
void setStructureDouble (struct Structure* structure, int p, double* dou)
{
if (structure[p].d_Float != NULL) free(structure[p].d_Float);
structure[p].d_Float = (double*) malloc (sizeof(double));
structure[p].d_Float = dou;
}
The most likely reason is that somewhere in your code you go out of bounds of the memory you allocated and thus destroy the integrity of the heap. A frequently encountered practical manifestation of such undefined behavior is a failure at free, when the library detects the problem with the heap.
Inside you allocation cycle you allocate just one object of each respective type for each field of your struct object. For example, you allocate only one character for c_Char field and initialize it with \0. This might suggest that c_Char is intended to hold a string (is it?). If so, then the memory you allocated is sufficient for an empty string only. If you do not reallocate that memory later, any attempts to place a longer string into that memory will break the integrity of the heap and trigger undefined behavior.
The same applies to other fields as well. However, without extra explanations from you it is not possible to say whether it is right or wrong. At least, you have to provide the definition of struct Structure. And you have to explain your intent. Why are you dynamically allocating single-object memory for struct fields instead of just making these objects immediate members of the struct?
The additional code you posted is completely and utterly broken.
Firstly you are calling your mutators as
setStructureNumber(structure, i,(int*) _i);
setStructureChar(structure, i, (char*) _c);
setStructureDouble(structure, i, &_d);
This does not make any sense. Why are you trying to convert integer value _i to pointer type??? If you want to obtain a pointer to _i, it is done as &_i. You already do it correctly in the very last call, where you pass &_d. Why are the first two calls different from the last one? What was your logic behind this?
Secondly, inside your mutator functions
void setStructureNumber (struct Structure* structure, int p, int* num)
{
if (structure[p].i_Number != NULL) free(structure[p].i_Number);
structure[p].i_Number = (int*) malloc (sizeof(int));
structure[p].i_Number = num;
}
you are freeing old memory and allocating new memory. Why? Why don't just reuse the old memory to store the new value? (BTW, there's no need to check the pointer for null before calling free, because free will check it internally anyway.)
Thirdly, after allocating the new memory you immediately leak it by overriding the pointer value returned by malloc with the pointer value passed from the outside
structure[p].i_Number = num;
Again, this does not make any sense. This is actually what causes the crash on free - the pointers you pass from the outside are either meaningless random values (like your (int *) _i or (char *) _c)) or point to a local variable (like your &_d).
There's no way to "correct" your code without knowing what it is you are trying to do in the first place. There are just too many completely unnecessary memory allocations and reallocations and other illogical things. I would simply rewrite the mutator functions as
void setStructureNumber (struct Structure* structure, int p, int num)
{
*structure[p].i_Number = num;
}
Note - no memory reallocations and the argument is passed by value.
The functions would be called as
setStructureNumber(structure, i, _i);
setStructureChar(structure, i, _c);
setStructureDouble(structure, i, _d);
But again, this is so vastly different from what you have that I don't know whether this is what you need.
Technically, there is nothing wrong with what you are doing (except the missing error checks on allocations, unnecessary casts of malloc results, and unnecessary NULL checking before calling free).
This should work fine, assuming that you pass the correct value of N, and that you do not free things more than once:
struct Structure * newStructure(int N) {
struct Structure * structure = malloc(N * sizeof(struct Structure));
for (int i = 0; i < N; i++) {
structure[i].i_Number = malloc(sizeof(int));
structure[i].c_Char = malloc(sizeof(char));
structure[i].c_Char[0] = '\0';
structure[i].d_Float = malloc(sizeof(double));
}
return structure;
}
void freeMemory (struct Structure* structure, int N)
{
for(int i=0 ; i<N ; i++ )
{
free(structure[i].i_Number);
free(structure[i].c_Char);
free(structure[i].d_Float);
}
free(structure);
}
You can use a memory diagnostic tool such as valgrind to ensure that you do not freeing things more than once.
In your mutators you leak memory and then point to local variables (comments mine)
void setStructureChar (struct Structure* structure, int p, char* str)
{
if (structure[p].c_Char != NULL) free(structure[p].c_Char);
// allocates new memory and points c_Char at it.
structure[p].c_Char = (char*) malloc (sizeof(char));
// makes c_Char point to where `str` is pointing; now the allocated memory is leaked
structure[p].c_Char = str;
}
When you later do free on structure[p].c_Char, it causes undefined behaviour because you called this function with a pointer to a local variable. You probably have undefined behaviour elsewhere too if you try to access c_Char anywhere before freeing it.
The other mutators have the same problem.
To "fix" this change structure[p].c_Char = str; to *structure[p].c_Char = *str;.
You also have blunders here:
setStructureNumber(structure, i,(int*) _i);
setStructureChar(structure, i, (char*) _c);
You meant &_i and &_c respectively. I would advise to remove all casts from your code. At best they are redundant; at worst (e.g. in these two lines) they hide an error which the compiler would diagnose.
Also remove all the NULL checks before free, they are redundant and make your code hard to read. Instead, do the NULL checks after calling malloc, and abort the program if malloc returned NULL.
However this whole setup seems like a ghastly design. You could pass the things by value to the mutators. And you could change your struct to not contain pointers, and therefore not need all this extra allocation.

Array of pointers issue

i'm having some troubles when passing data from one pointer to an element of an array of pointers of an struct.
typedef struct {
float* data;
int size;
} vector;
//This function creates the vector
vector* doVector(int n, float* data){
vector * vec = (vector *) malloc(sizeof(vector));
vec->size = n;
vec->data = data;
return vec;
}
void delVector(vector* v){
free(v->data);
free(v);
}
void prVector(vector* v)
{
printf("[");
for(unsigned int i = 0; i<v->size; i++){
if(i!=v->size-1)
printf("%f,", v->data[i]);
else
printf("%f]\n", v->data[i]);
}
}
void fillVectors(float* data,int size){
vector * vectors = (vector*) malloc(size * sizeof(vector));
for(unsigned int i = 0; i < size; i++){
vectors[i] = *doVector(size,data);//This gives trouble
prVector(&vectors[i]);
}
//More stuff will be added here to work with the vectors.
for(unsigned int i = 0; i < size; i++)
delVector(&vectors[i]);//Memory leak here obv
free(vectors);// I also need to free the array
}
int main()
{
//Here recieving data from file and calling fillVectors
//Also allocating memory for data (which is send to fillvectors)
//Avoided to post because it's irrelevant and big
}
So the main idea is to create vectors with the struct,Data and size is read from file and stored into float array called data and int size. Then we call the function fillVector, which will call the doVector function and create the vector itself.
Then I want to assign the value of each vector to a position of the pointer array,(there are 3 mallocs, data and single vector, which is made in doVector, and the array of vectors made in fillVectors).
Problem comes when freeing this pointers, keep getting memory leaks.
Has something to do with the malloc of the array of vectors and the vector malloc from doVector.
ps: fillVector function is only called once
thanks.
Simple rule: in C if want to process smth in function send pointer. So if want to delete vector by pointer then pass pointer to pointer
void delVector(vector** v){
free((*v)->data);
free(*v);
*v = NULL;
}
Function already returns pointer so no need to use asterisk sign.
vectors[i] = *doVector(size,data);
Second: you want array of vectors? so use array of pointers to vectors
vector **vectors = (vector**) malloc(size * sizeof(vector*));
for (unsigned int i = 0; i < size; i++){
vectors[i] = doVector(size, data);//This gives trouble
prVector(vectors[i]);//no need to use ampersand, it is already pointer
}
And main: you need deep copy of float data inside vector. Now all vectors keep pointer to same array, given as argument. And beside that, you delete this data
free(v->data);
But this pointer was copied, but not owned.
vector* doVector(size_t n, float* data){
size_t i;
vector * vec = (vector *) malloc(sizeof(vector));
vec->size = n;
vec->data = (float*)malloc(sizeof(float) * n);
for (i = 0; i < n; i++) {
vec->data[i] = data[i];
}
//or just
//memcpy(vec->data, data, n*sizeof(float));
return vec;
}
More questions...
I will focus on your line with the comment //This gives trouble
With function doVector you use malloc to create a vector instance somewhere in memory. Then, when dereferencing the result by doing *doVector(size, data), you take the created vector and try to assign it to vectors[i]. This copies the memory block of newly created vector into the location vectors[i], but you don't keep the pointer to the result of doVector.
Afterwards, you free the memory of vectors element by element in the for loop and later you try to free the same space again using free(vectors) after the for loop. However, the memory allocated inside doVector is never freed, because you don't have the pointers to created vectors.
I would stick to Ivan Ivanov's answer for making it correct. I just wanted to point out why it doesn't work.
You should be initializing all pointers created and not IMMEDIATELY allocated to NULL or 0 or (void*)0. Then a call to free will clean up any allocated data.
Whenever allocating the actual data type make sure that you set the internal ptr to NULL before you allocate it as well.
C
vector* newVector;
newVector = (void*)0; //or 0, NULL
... //Code here
newVector = malloc(sizeof(vector));
newVector->data = (void*)0;
... //More code
if(!newVector){
free(newVector);
newVector = (void*)0;
}
Notes
If you must do dynamic memory allocation, do it in a format where you manage pointers with a static value.
As Chris mentions below, deleting a null ptr is already handled by delete and free, but I like to include the if statements to remind myself to set the pointer to NULL when its absolutely necessary.
Thanks again Chris :D

How can I set a certain value to a member of a struct within multiple functions?

i am a beginner so please cut me some slack on this one. So I have two functions and a struct in a header file I am currently working with.
This is the struct:
typedef struct ArrayList
{
// We will store an array of strings (i.e., an array of char arrays)
char **array;
// Size of list (i.e., number of elements that have been added to the array)
int size;
// Length of the array (i.e., the array's current maximum capacity)
int capacity;
} ArrayList;
Here is the first function, which creates and dynamically allocates memory for an array of strings. Capacity is the length of the internal array and size is the current size (how many strings are in the array which is essentially 0.)
ArrayList *createArrayList(int length){
char **array = NULL;
ArrayList *n;
int size = 0;
if (length > DEFAULT_INIT_LEN)
{
array = malloc(sizeof(int) * length);
n->capacity = length;
}
else
{
array = malloc(sizeof(int) * DEFAULT_INIT_LEN);
n->capacity = DEFAULT_INIT_LEN;
}
if (array == NULL)
panic("ERROR: out of memory in Mylist!\n");
n->size = size;
printf("-> Created new ArrayList of size %d\n", n->capacity);
return *array;
When I try to implement a pointer to the capacity member of the ArrayList struct inside another function within the same file, it is uninitialized instead of set as the value from the previous function. I.e. in createArrayList, n->capacity is equal to 10, but when used in printArrayList it is uninitialized and a random number appears such as 122843753.:
void printArrayList(ArrayList *list)
{
printf("\n%d", list->capacity);
return NULL;
}
My question is, how can I make it so all these functions "share" the same value when referring to the struct members. I.E. the first function prints -> Created new ArrayList of size 10, and the second function prints 10 as well. Also, I have to do this without changing the struct function itself. Sorry if this is a poorly worded question, but I can further clarify if it is confusing. Thanks in advance!
I see a couple of major issues with this code, in createArrayList you are returning array which is a char ** but you should be returning an ArrayList * which is what n is. So it looks like you want to assign array to n->array. The next issue is that n is an ArrayList * but you do not allocate memory for n.

Resources