Passing pointer to pointer for reallocation in function - c

I'm a beginner C programmer and have issues implementing an (ordered) dynamic array of structs.
Before adding an element to the array, I want to check if it is full and double it's size in that case:
void insert_translation(dict_entry **dict, char *word, char *translation){
if( dictionary_entries == dictionary_size ){
dict_entry *temp_dict;
temp_dict = realloc(&dict, (dictionary_size *= 2) * sizeof(dict_entry) );
// printf("Increased dict size to %d\n", dictionary_size);
// if(temp_dict == NULL){
// fprintf(stderr, "Out of memory during realloc()!\n");
// /*free(dict);
// exit(EXIT_OUT_OF_MEMORY);*/
// }
//free(dict);
//*dict = temp_dict;
}
dictionary_entries++;
printf("Inserted %s into dict - %d of %d filled.\n", word, dictionary_entries, dictionary_size);
}
I call the function from the main function like this:
dictionary_size = 2; //number of initial key-value pairs (translations)
dictionary_entries = 0;
dict_entry *dictionary = malloc(dictionary_size * sizeof(dict_entry));
[...]
insert_translation(&dictionary, "bla", "blub");
In my understanding, dictionary is a pointer to a space in memory. &dictionary is a pointer to the pointer, which I pass to the function. In the function, dict is said pointer to pointer, so &dict should be the pointer to the area in memory? However, when I try to compile, I get the following error message:
pointer being realloc'd was not allocated
Edit
I expanded the code sample to show more of the code in the main function.

The problem is in this statement
temp_dict = realloc(&dict, (dictionary_size *= 2) * sizeof(dict_entry) );
The parameter dict has the type
dict_entry **dict
in the statement that reallocs the memory you have to use the value of the pointer *dic but you are uisng an expression &dict that has the type dict_entry ***.
Compare the type of the left side of the assignment
ict_entry *temp_dict
with the type of the reallocated pointer. They should be the same (except in C one of them can have the type void *)
So you need to write
temp_dict = realloc(*dict, (dictionary_size *= 2) * sizeof(dict_entry) );
^^^^^
In C arguments are passed by value. If you want to change the original value of an argument you should to pass it by reference through a pointer to the argument. In the function you need to dereference the pointer that to change the object pointed to by the pointer.

&dict -> *dict. You can simplify the code by using a return type, to avoid such bugs:
dict_entry* insert_translation(dict_entry* dict, char *word, char *translation)
{
...
if( dictionary_entries == dictionary_size )
{
dictionary_size *= 2;
dict_entry *tmp = realloc(dict, sizeof(dict_entry[dictionary_size]));
if(tmp == NULL)
{
// error handling, free(dict) etc
}
else
{
dict = tmp;
}
}
...
return dict;
}

Related

How to generically assign a pointer passed into a function in C

I am new to C and wondering how to do some pointer stuff. Specifically here I am wondering how you can pass a pointer into a function and "get a value out of the function". Sort of like this (semi-pseudocode):
assign_value_to_pointer(void* pointer) {
if (cond1) {
pointer = 10;
} else if (cond2) {
pointer = "foo";
} else if (cond3) {
pointer = true;
} else if (cond4) {
pointer = somestruct;
} else if (cond5) {
pointer = NULL;
} else if (cond6) {
// unknown type!
pointer = flexiblearraymember.items[index];
}
}
main() {
void* pointer = NULL;
assign_value_to_pointer(&pointer);
if (cond1) {
assert(pointer == 10);
} else if (cond2) {
assert(pointer == "foo");
} else if (cond3) {
assert(pointer == true);
} else if (cond4) {
assert(pointer == somestruct);
} else if (cond5) {
assert(pointer == NULL);
}
}
Put another way:
p = new Pointer()
assign_a_value(p)
assert(p.value == 10) // or whatever
Basically it is passing the pointer into the function, the function is assigning a value to the pointer, and then you can use that value outside of the function when it returns. You may not know what kind of value you are getting from the function (but that can be handled by extending this to use structs and such), hence the void pointer. The main goal though is just passing a pointer into some function and having it absorb some value.
Wondering how to do this properly in C with a quick example implementation. Doesn't have to cover every case just enough to get started.
I would like to use this to implement stuff like passing in a NULL error object to a function, and if there is an error, it sets the pointer of the error to some error code, etc.
I don't think this should be a broad question, but if it is, it would be helpful to know where to look for a more thorough explanation or examples in source code.
First, I'll answer your question directly, hopefully you understand why you need to be reaaally careful. This can be a useful technique for implementing queues, or communication stacks - but you need to be CERTAIN that you can regain track of what types are being stored or your program logic will totally break. I'll then try to briefly cover some of the use cases and some methods of making it safe(r).
Simple example doing exactly what you said
#include <stdio.h>
#include <stdlib.h>
//Some basic error type for reporting failures
typedef enum my_error
{
ERROR_NONE = 0,
ERROR_FAIL = 1,
} my_error;
struct my_struct
{
int age;
char *name;
int order_count;
};
int someCond = 1;
//Let's start with a simple case, where we know the type of the pointer being passed (an int)
//If int_out is NULL, then this function will invoke undefined behavior (probably a
//runtime crash, but don't rely on it).
my_error assign_int(int *int_out)
{
if(someCond)
*int_out = 5;
else
*int_out = 38;
return ERROR_NONE;
}
//Need to use a 'double pointer', so that this function is actually changing the pointer
//that exists in the parent scope
my_error dynamically_assign_value_to_pointer(void **pointer)
{
//A pointer internal to this function just to simplify syntax
void *working_ptr = NULL;
if(someCond)
{
//Allocate a region of memory, and store its location in working_ptr
working_ptr = malloc(sizeof(int));
//store the value 12 at the location that working_ptr points to (using '*' to dereference)
*((int *) working_ptr) = 12;
}
else
{
//Allocate a region of memory, and store its location in working_ptr
working_ptr = malloc(sizeof(struct my_struct));
//Fill the struct with data by casting (You can't dereference a void pointer,
//as the compiler doesn't know what it is.)
((struct my_struct *) working_ptr)->age = 22;
((struct my_struct *) working_ptr)->name = "Peter";
((struct my_struct *) working_ptr)->order_count = 6;
}
//Set the pointer passed as an argument to point to this data, by setting the
//once-dereferenced value
*pointer = working_ptr;
return ERROR_NONE;
}
int main (int argc, char *argv[])
{
int an_int;
void *some_data;
assign_int(&an_int);
//an_int is now either 5 or 38
dynamically_assign_value_to_pointer(&some_data);
//some_data now points to either an integer OR a my_struct instance. You will need
//some way to track this, otherwise the data is useless.
//If you get this wrong, the data will be interpreted as the wrong type, and the
//severity of the issue depends what you do with it.
//For instance, if you KNOW FOR SURE that the pointer contains the int, you could
//print it by:
printf("%d", *((int *) some_data));
//And because it is dynamically allocated, you MUST free it.
free(some_data);
return 0;
}
In practice, this is useful for queues, for instance, so you can write a generic queue function and then have different queues for different data types. This is partial code, so won't compile and is a bad idea in this limited case, when a type-safe alternative would be trivial to design, but hopefully you get the idea:
extern my_queue_type myIntQueue;
extern my_queue_type myStructQueue;
my_error get_from_queue(void *data_out, my_queue_type queue_in);
int main (int argc, char *argv[])
{
//...
int current_int;
struct my_struct current_struct;
get_from_queue(&current_int, myIntQueue);
get_from_queue(&current_struct, myStructQueue);
//...
}
Or if you really want to store lots of different types together, you should at least track the type along with the pointer in a struct, so you can use a 'switch' in order to cast and handle logic appropriately when necessary. Again, partial example so won't compile.
enum my_types
{
MY_INTEGER, MY_DOUBLE, MY_STRUCT
};
struct my_typed_void
{
void *data;
enum my_types datatype;
};
my_error get_dynamic_from_global_queue(struct my_typed_void *data_out)
{
//...
data_out->data = malloc(sizeof int);
*((int *)(data_out->data)) = 33;
data_out->datatype = MY_INTEGER;
//...
}
int main (int argc, char *argv[])
{
struct my_typed_void current;
if(get_dynamic_from_global_queue(&current) == ERROR_NONE)
{
switch(current.datatype)
{
//...
case MY_INTEGER:
printf("%d", *((int *) current.data));
break;
//...
}
free(current.data);
}
return 0;
}
Either return the pointer or pass a pointer to pointer (the function then will change the pointer):
void* f1(void* p)
{
p = whatever(p, conditions);
return p;
}
void f2(void** p)
{
*p = whatever(*p, conditions);
}
void assign_value_to_pointer(int** pointer) {
**pointer = 20;
}
void main() {
void* pointer = NULL;
pointer=malloc(sizeof(int));
*(int *)pointer=10;
assign_value_to_pointer(&pointer);
}
I'm not 100% sure what you are looking for, but could it be something like this:
enum pointer_type{INTEGER, STRUCTURE_1, STRUCTURE_2, INVALID};
int assign_value_to_pointer(void ** ptr)
{
uint8_t cond = getCondition();
switch(cond)
{
case 1:
*ptr = (void*) 10;
return INTEGER;
case 2:
*ptr = (void*) someStructOfType1;
return STRUCTURE_1;
case 3:
*ptr = (void*) someStructOfType2;
return STRUCTURE_2;
default:
*ptr = NULL;
return INVALID;
};
}
void main(void)
{
void * ptr = NULL;
int ptrType = assign_value_to_pointer(&ptr);
switch(ptrType)
{
case INTEGER:
assert(ptr == (void*)10);
break;
case STRUCTURE_1:
assert( ((structType1*) ptr)->thing == something);
break;
case STRUCTURE_2:
assert( ((structType2*) ptr)->something == something);
break;
default:
assert(ptr == NULL);
}
}
You can actually type cast the pointer in main() according to the case (condition) and use. However, in my opinion, you can use a union for this purpose.
Create a union with all possible data types.
typedef union _my_union_type_ {
int intVal;
char* stringVal;
bool boolVal;
SomestructType somestruct;//Assuming you need a structure not structure pointer.
void* voidPtrType;
} my_union_type;
Now in main(), create variable of this union type and pass the address of the union to the function.
main() {
my_union_type my_union;
memset(&my_union, 0x00, sizeof(my_union));
assign_value_to_pointer(&my_union);
if (cond1) {
assert(my_union.intVal == 10);
} else if (cond2) {
assert(strcmp(my_union.stringVal, "foo")); //String comparison can not be done using '=='
} else if (cond3) {
assert(my_union.boolVal == true);
} else if (cond4) {
assert(memcmp(&my_union.somestruct, &somestruct, sizeof(somestruct)); //Assuming structure not structure pointer.
} else if (cond5) {
assert(my_union.voidPtrType == NULL);
} else if (cond5) {
//Check my_union.voidPtrType
}
}
And in assign_value_to_pointer, you can store the required value in union variable.
assign_value_to_pointer(my_union_type* my_union) {
if (cond1) {
my_union->intVal = 10;
} else if (cond2) {
my_union->stringVal = "foo";
} else if (cond3) {
my_union->boolVal = true;
} else if (cond4) {
memcpy(&(my_union->somestruct), &somestruct, sizeof(somestruct));
} else if (cond5) {
my_union->voidPtrType = NULL;
} else if (cond6) {
// unknown type!
my_union->voidPtrType = flexiblearraymember.items[index];
}
}
I would like to use this to implement stuff like passing in a NULL error object to a function, and if there is an error, it sets the pointer of the error to some error code, etc.
From the above quote and from the code in the question, it seems you are looking for a variable that can "hold" different types, i.e. sometimes you want it to be an integer, at other times a float, at other times a string and so on. This is called a variant in some languages but variants doesn't exist in C. (see this https://en.wikipedia.org/wiki/Variant_type for more about variants)
So in C you'll have to code your own variant type. There are several ways to do that. I'll give examples below.
But first a few words on pointers in C because the code in the question seem to reveal a misunderstanding as it assigns values directly to the pointer, e.g. pointer = somestruct; which is illegal.
In C is very important to understand the difference between the "value of a pointer" and the "value of the pointed to object". The first, i.e. value of a pointer, tells where the pointer is pointing, i.e. the value of a pointer is the address of the pointed to object. Assignments to a pointer changes where the pointer is pointing. To change the value of the pointed to object, the pointer must be dereferenced first. Example (pseudo code):
pointer = &some_int; // Make pointer point to some_int
*pointer = 10; // Change the value of the pointed to object, i.e. some_int
// Notice the * in front of pointer - it's the dereference
// that tells you want to operate on the "pointed to object"
pointer = 10; // Change the value of the pointer, i.e. where it points to
// In other words, pointer no longer points to some_int
Now back to the "variant" implementation. As already mentioned there are several ways to code that in C.
From your question it seems that you want to use a void-pointer. It's doable and I'll start by showing an example using void-pointer and after that an example using a union.
It's not clear in your question what cond are so in my examples I'll just assume it's a command line argument and I just added some interpretation in order to have a running example.
The common pattern for the examples is the use of a "tag". That is an extra variable that tells the current type of objects value (aka meta-data). So the general variant data type looks like:
struct my_variant
{
TagType tag; // Tells the current type of the value object
ValueType value; // The actual value. ValueType is a type that allows
// storing different object types, e.g. a void-pointer or a union
}
Example 1 : void-pointer and casts
The example below will use a void-pointer to point to the object containing the real value. A value that sometimes is an integer, sometimes a float or whatever is needed. When working with a void-pointer, it's necessary to cast the void-pointer before dereferencing the pointer (i.e. before accessing the pointed to object). The tag field tells the type of the pointed to object and thereby also how the cast shall be.
#include <stdio.h>
#include <stdlib.h>
// This is the TAG type.
// To keep the example short it only has int and float but more can
// be added using the same pattern
typedef enum
{
INT_ERROR_TYPE,
FLOAT_ERROR_TYPE,
UNKNOWN_ERROR_TYPE,
} error_type_e;
// This is the variant type
typedef struct
{
error_type_e tag; // The tag tells the type of the object pointed to by value_ptr
void* value_ptr; // void pointer to error value
} error_object_t;
// This function evaluates the error and (if needed)
// creates an error object (i.e. the variant) and
// assigns appropriate values of different types
error_object_t* get_error_object(int err)
{
if (err >= 0)
{
// No error
return NULL;
}
// Allocate the variant
error_object_t* result_ptr = malloc(sizeof *result_ptr);
// Set tag value
// Allocate value object
// Set value of value object
if (err > -100) // -99 .. -1 is INT error type
{
result_ptr->tag = INT_ERROR_TYPE;
result_ptr->value_ptr = malloc(sizeof(int));
*(int*)result_ptr->value_ptr = 42;
}
else if (err > -200) // -199 .. -100 is FLOAT error type
{
result_ptr->tag = FLOAT_ERROR_TYPE;
result_ptr->value_ptr = malloc(sizeof(float));
*(float*)result_ptr->value_ptr = 42.42;
}
else
{
result_ptr->tag = UNKNOWN_ERROR_TYPE;
result_ptr->value_ptr = NULL;
}
return result_ptr;
}
int main(int argc, char* argv[])
{
if (argc < 2) {printf("Missing arg\n"); exit(1);}
int err = atoi(argv[1]); // Convert cmd line arg to int
error_object_t* err_ptr = get_error_object(err);
if (err_ptr == NULL)
{
// No error
// ... add "normal" code here - for now just print a message
printf("No error\n");
}
else
{
// Error
// ... add error handler here - for now just print a message
switch(err_ptr->tag)
{
case INT_ERROR_TYPE:
printf("Error type INT, value %d\n", *(int*)err_ptr->value_ptr);
break;
case FLOAT_ERROR_TYPE:
printf("Error type FLOAT, value %f\n", *(float*)err_ptr->value_ptr);
break;
default:
printf("Error type UNKNOWN, no value to print\n");
break;
}
free(err_ptr->value_ptr);
free(err_ptr);
}
return 0;
}
Some examples of running this program:
> ./prog 5
No error
> ./prog -5
Error type INT, value 42
> ./prog -105
Error type FLOAT, value 42.419998
> ./prog -205
Error type UNKNOWN, no value to print
As the example above shows, you can implement a variant type using void-pointer. However, the code requires a lot of casting which makes the code hard to read. In general I'll not recommend this approach unless you have some special requirements that forces the use of void-pointer.
Example 2 : pointer to union
As explained earlier C doesn't have variants as they are known in other languages. However, C has something that is pretty close. That is unions. A union can hold different types at different times - all it misses is a tag. So instead of using a tag and a void-pointer, you can use a tag and a union. The benefit is that 1) casting will not be needed and 2) a malloc is avoided. Example:
#include <stdio.h>
#include <stdlib.h>
typedef enum
{
INT_ERROR_TYPE,
FLOAT_ERROR_TYPE,
UNKNOWN_ERROR_TYPE,
} error_type_e;
// The union that can hold an int or a float as needed
typedef union
{
int n;
float f;
} error_union_t;
typedef struct
{
error_type_e tag; // The tag tells the current union use
error_union_t value; // Union of error values
} error_object_t;
error_object_t* get_error_object(int err)
{
if (err >= 0)
{
// No error
return NULL;
}
error_object_t* result_ptr = malloc(sizeof *result_ptr);
if (err > -100) // -99 .. -1 is INT error type
{
result_ptr->tag = INT_ERROR_TYPE;
result_ptr->value.n = 42;
}
else if (err > -200) // -199 .. -100 is FLOAT error type
{
result_ptr->tag = FLOAT_ERROR_TYPE;
result_ptr->value.f = 42.42;
}
else
{
result_ptr->tag = UNKNOWN_ERROR_TYPE;
}
return result_ptr;
}
int main(int argc, char* argv[])
{
if (argc < 2) {printf("Missing arg\n"); exit(1);}
int err = atoi(argv[1]); // Convert cmd line arg to int
error_object_t* err_ptr = get_error_object(err);
if (err_ptr == NULL)
{
// No error
// ... add "normal" code here - for now just print a message
printf("No error\n");
}
else
{
// Error
// ... add error handler here - for now just print a message
switch(err_ptr->tag)
{
case INT_ERROR_TYPE:
printf("Error type INT, value %d\n", err_ptr->value.n);
break;
case FLOAT_ERROR_TYPE:
printf("Error type FLOAT, value %f\n", err_ptr->value.f);
break;
default:
printf("Error type UNKNOWN, no value to print\n");
break;
}
free(err_ptr);
}
return 0;
}
In my opinion this code is easier to read than the code using void-pointer.
Example 3 : union - no pointer - no malloc
Even if example 2 is better than example 1 there is still dynamic memory allocation in example 2. Dynamic allocation is part of most C programs but it is something that shall be used only when really needed. In other words - objects with automatic storage duration (aka local variables) shall be prefered over dynamic allocated objects when possible.
The example below shows how the dynamic allocation can be avoided.
#include <stdio.h>
#include <stdlib.h>
typedef enum
{
NO_ERROR,
INT_ERROR_TYPE,
FLOAT_ERROR_TYPE,
UNKNOWN_ERROR_TYPE,
} error_type_e;
typedef union
{
int n;
float f;
} error_union_t;
typedef struct
{
error_type_e tag; // The tag tells the current union usevalue_ptr
error_union_t value; // Union of error values
} error_object_t;
error_object_t get_error_object(int err)
{
error_object_t result_obj;
if (err >= 0)
{
// No error
result_obj.tag = NO_ERROR;
}
else if (err > -100) // -99 .. -1 is INT error type
{
result_obj.tag = INT_ERROR_TYPE;
result_obj.value.n = 42;
}
else if (err > -200) // -199 .. -100 is FLOAT error type
{
result_obj.tag = FLOAT_ERROR_TYPE;
result_obj.value.f = 42.42;
}
else
{
result_obj.tag = UNKNOWN_ERROR_TYPE;
}
return result_obj;
}
int main(int argc, char* argv[])
{
if (argc < 2) {printf("Missing arg\n"); exit(1);}
int err = atoi(argv[1]); // Convert cmd line arg to int
error_object_t err_obj = get_error_object(err);
switch(err_obj.tag)
{
case NO_ERROR:
printf("No error\n");
break;
case INT_ERROR_TYPE:
printf("Error type INT, value %d\n", err_obj.value.n);
break;
case FLOAT_ERROR_TYPE:
printf("Error type FLOAT, value %f\n", err_obj.value.f);
break;
default:
printf("Error type UNKNOWN, no value to print\n");
break;
}
return 0;
}
Summary
There are many ways of solving the problem addressed by OP. Three examples have been given in this answer. In my opinion example 3 is the best approach as it avoids dynamic memory allocation and pointers but there may be situations where example 1 or 2 is better.
You are not far from success, you just miss an asterisk to dereference the argument:
void assign_value_to_pointer(void* pointer) {
if (cond1) {
*pointer = 10; // note the asterisk
...
}
void main() {
void* pointer = NULL;
assign_value_to_pointer(&pointer);
}
In C language, arguments to functions are always passed by value. If you want the function to modify the argument, you must pass the address of the variable you want to modify. In main(), you are doing that - correct. The called function can write where its argument points to, hence modifying the original variable; to do this, you must dereference the argument.
The compiler should get angry on the assignment, because it does not know how many bytes to write (I'm keeping it simple). So, you have to say what kind of object the pointer points to, like this:
*(int *) pointer = 10;
The typecast you choose is up to you, it depends on the context.
At this point... why not declare differently the function:
void assign_value_to_pointer(int* pointer) {
if (cond1) {
*pointer = 10; // note the asterisk
}
Now the typecast is no more necessary because the compiler knows the kind of object (again I am keeping it simple - void is quite special).
******* EDIT after comments
Well, I am not a guru in C language and, besides, I wanted to keep a low profile to better help the OP.
For simple cases, the right declaration is naive. The typecast can be more flexible because the function can have several assignment statements to choose from depending on context. Lastly, if the function is passed the pointer and some other parameter, everything is possible, including using memcpy(). But this last solution opens up a world...
To reply to Lance (comment below): well, I think that there is no way to do an assignment if you don't know the type of object you are writing to. It seems a contracdition to me...

C: Stack element overwritten by a function call

I'm doing a school assignment, I've I've run into 2 problems. I have to simulate stacks, with arrays.
My current code is as follows:
#include <stdlib.h>
#include <stdio.h>
typedef struct {
int capacity;
int * array;
int size;
} stack_tt;
int pop(stack_tt * stack_p);
void push(stack_tt * stack_p, int value);
int top(stack_tt * stack_p);
stack_tt * newStack(void);
int empty(stack_tt * stack_p);
int main() {
stack_tt * myStack = newStack();
push(myStack, 123);
push(myStack, 99);
push(myStack, 4444);
while (!empty(myStack)) {
int value;
value = pop(myStack);
printf("popped: %d\n", value);
}
return 0; }
stack_tt * newStack(){
stack_tt * newS = malloc(sizeof(stack_tt) * 20);
(*newS).capacity = 1;
(*newS).size = 0;
return newS;
}
void push(stack_tt * stack_p, int value){
if ((*stack_p).size >= (*stack_p).capacity) {
(*stack_p).capacity*=2;
//realloc(stack_p, stack_p->capacity * sizeof(stack_tt));
}
(*stack_p).array = &value;
(*stack_p).size++;
}
int pop(stack_tt * stack_p){
(*stack_p).size--;
int fap = *(*stack_p).array;
return fap;
}
int empty(stack_tt * stack_p){
if ((*stack_p).size >= 1)
return 0;
return 1;
}
Fist of, when I call the line
while(!empty(myStack))
It changes the value in my array to 1.
secondly I'm not able to change individual values in my array, whenever I try things like:
(*stack_p).array[0] = value;
It doesn't know where in the memory to look.
I hope someone is able to help me out :)
There are a couple of problems with the code as I see it.
Lets take the push function where you do
(*stack_p).array = &value;
That will make the array structure member point to the local variable value, and once the function returns the variable cease to exist leaving you with a stray pointer and using that pointer will lead to undefined behavior.
The second problem with that code is that your stack will only be pointing (illegally) to the last element added.
You must allocate memory explicitly for array and use capacity to keep track of how much memory is allocated. The use size as an index into the allocated array for the pushing and popping. Something like
stack_tt * newStack(){
stack_tt * newS = malloc(sizeof(stack_tt)); // Only allocate *one* structure
newS->capacity = 0; // Start with zero capacity
newS->size = 0;
newS->array = NULL;
return newS;
}
void push(stack_tt * stack_p, int value){
if (stack_p->size + 1 > stack_p->capacity){
// Increase capacity by ten elements
int new_capacity = stack_p->capacity + 10;
int * temp_array = realloc(stack_p->array, new_capacity * sizeof(int));
if (temp_srray == NULL)
return;
stack_p->capacity = new_capacity;
stack_p->array = temp_array;
}
stack_p->array[stack_p->size++] = value;
}
int pop(stack_tt * stack_p){
if (stack_p->size > 0)
return stack_p->array[--stack_p->size];
return 0;
}
int empty(stack_tt * stack_p){
return stack_p->size == 0;
}
There is no need to allocate space for 20 structs of type stack_tt, you only need to allocate space for one:
stack_tt * newS = malloc(sizeof(stack_tt));
however you need to allocate space for elements of the struct member array:
newS->array = malloc( sizeof(int)*20);
newS->size = 0;
newS->capacity = 20;
now you can use the array member.
When you push a value to the 'stack', you shouldn't overwrite the array member with the address of the local variable, that doesn't make sense and will cause undefined behavior in addition of loosing the previously allocated memory. Instead simply assign the value to the member array, in the function push:
stack_p->array[stack_p->size] = value;
stack_p->size++;
Similarly when you pop an element, take the current element from the member array:
stack_p->size--;
int fap = stack_p->array[stack_p->size];
The rest of the functions and code should be fixed in the same manner.
You're code is good, but probably you didn't understand the usage of realloc:
//realloc(stack_p, stack_p->capacity * sizeof(stack_tt));
This function returns a pointer to the newly allocated memory, or NULL if the request fails.
The realloc (as the function suggests) takes the memory pointed by the pointer you pass, and copies that memory block in a new and resized block. So the right code should be.
stack_p->array = realloc(stack_p->array, stack_p->capacity * sizeof(stack_tt));
This other line is wrong:
(*stack_p).array = &value;
Change it with:
stack_p->array[stack_p->size] = value;
Another little suggestion, every (*stack_p). can be replaced by stack_p->, which is more elegant.
In the newStack() you're mallocing 20 structs which is kinda useless. You just need one.
Then you should malloc the array for the first time:
newS->array = malloc(sizeof(int));
newS->capacity = 1;

How to malloc an array of structures [duplicate]

This question already has answers here:
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 6 years ago.
I would like to know how to malloc (and hen realloc) an array of a structure.
Here is my structure :
typedef struct tag {
char *key;
char *val;
} tag;
I use this structure in another structure :
typedef struct node {
int id;
double lat;
double lon;
int visible;
tag *tab;
} node;
I define a node *n, then:
n->tab = (tag*)malloc(sizeof(tag) * 5);
but I have an error of malloc corruption.
void remplisTag(xmlNodePtr cur, node *n) {
xmlNodePtr fils;
n->tab = malloc(sizeof(*n->tab) * 5);
if (n->tab == NULL) {
error(E_ERROR_MALLOC);
}
printf("apres malloc\n");
int taille = 5;
int ind = 0;
xmlAttrPtr attr1, attr2;
xmlChar *key;
xmlChar *value;
fils = cur->xmlChildrenNode;
fils = fils->next;
while (xmlStrcmp(fils->name, (const xmlChar*)"text") != 0) {
if (xmlStrcmp(fils->name, (const xmlChar*)"tag") == 0) {
if (ind == taille - 1) {
n->tab = realloc(n->tab, sizeof(tag) * (taille + 5));
taille = taille + 5;
} else {
taille = taille;
}
/* searching for key */
attr1 = xmlHasProp(fils, (const xmlChar*)"k");
if (attr1 == NULL) {
error(E_KEY);
} else {
key = xmlGetProp(fils, (const xmlChar*)"k");
if (key == NULL) {
error(E_KEY_V);
}
/* searching for value */
attr2 = xmlHasProp(fils, (const xmlChar*)"v");
if (attr2 == NULL) {
error(E_VALUE);
}
value = xmlGetProp(fils, (const xmlChar*)"v");
if (value == NULL) {
error(E_VALUE_V);
}
tag t;
t.key = malloc(sizeof((char*)key));
strcpy(t.key, (char*)key);
strcpy(t.val, (char*)value);
t.val = malloc(sizeof((char*)value));
n->tab[ind++] = t;
}
}
fils = fils->next;
}
free(n->tab);
}
In main:
node *n = malloc(sizeof(node));
xmlNodePtr cur;
in a while loop:
remplisTag(cur, n);
There is a memory allocation issue in the following lines
tag t;
t.key = malloc(sizeof((char*)key));
strcpy(t.key, (char*)key);
strcpy(t.val, (char*)value);
t.val = malloc(sizeof((char*)value));
The memory in C is very fiddly - when you allocate memory, you need to hold enough to store the data.
tag t;
t.key = malloc(sizeof((char*)key));
strcpy(t.key, (char*)key);
Creates enough for a pointer -which is probably not enough.
The fix is something like.
tag t;
t.key = strdup( key );
t.val = strdup( value );
The strdup function combines the malloc (of the correct size) and the strcpy.
There is no visible problem in your allocation statement, some people prefer that malloc() return value not be cast to the destination type, and it is slightly more reliable to use the type of the destination pointer to avoid type mismatches that would be hard to detect:
n->tab = malloc(sizeof(*n->tab) * 5);
What is the precise error message you get?
Is it a runtime error?
How did you allocate the node structure that n points to?
Can you post the full code to the function that produces this failure?
A runtime message from malloc() is an indication that the memory allocation structures used internally by malloc have been corrupted. It would indicate that the problem is elsewhere, probably a buffer overrun in another object allocated by malloc(). Check the code that was executed since the previous call to malloc().
EDIT:
In the code posted, there are some allocation errors:
t.key = malloc(sizeof((char*)key));
strcpy(t.key, (char*)key);
strcpy(t.val, (char*)value);
t.val = malloc(sizeof((char*)value));
The space you allocate is just the size of a pointer char*, not the length of the string plus 1 for the final null terminator. If key is longer than 3 or 7 bytes, depending on the architecture, you have a buffer overrun.
t.val is allocated after you copy contents to it. Undefined behavior!
You should simplify this with strdup():
t.key = strdup((char*)key);
t.val = strdup((char*)value);
Your test for reallocation is too conservative: the array should be reallocated when ind == taille:
if (ind == taille) {
n->tab = realloc(n->tab, sizeof(*n->tab) * (taille + 5));
taille += 5;
}
taille and ind should be stored into the node to keep track of how much space has been allocated and how many tags are present. The current code does not provide this information to the caller, the rest of the tag array is uninitialized, there is no way to tell, undefined behavior is lurking.
Note that there are too many casts in your code. Casts prevent some type mismatch detection by the compiler, it is wise to change the argument types for your functions to avoid unnecessary casts.
For example: libxml2 defines xmlChar as a typedef for unsigned char. This is a very bad design decision. They should use char and handle the strings correctly regardless of whether char happens to be signed or unsigned on the current environment. This choice forces programmers to cast most arguments to the xmlXXX APIs, making the code ugly and error prone. You cannot change that, but you could use inline functions to convert between char* and xmlChar* to keep casts to a minimum.

creating an array containing pointers

I'm trying to create an array of pointers in C. Each value of the array should be a pointer to a struct (let's call it struct Type*).
Should i do
struct Type* myVariable= malloc(sizeof(struct Type*)*MY_SIZE);
or
struct Type** myVariable= malloc(sizeof(struct Type*)*MY_SIZE);
The second one looks like what i should do when i want to create a two dimensional array, which are an array of pointer, and those pointers are used to create arrays of the wanted type.
EDIT : But in my case the second dimension size would be only one
The first one looks like a regular array with int* as the contained values type.
How can i pass the good solution to a function (by pointer, not by value because the array may be fairly large) and use it in the fonction ?
The second one the right solution. However, you'll need to allocate memory for the objects too. Also, make sure to check the value returned by malloc.
// Allocate memory for the array of pointers.
struct Type** myVariable = malloc(sizeof(struct Type*)*MY_SIZE);
if ( myVariable == NULL )
{
// Deal with error
exit(1);
}
for (int i = 0; i < MY_SIZE; ++i )
{
// Allocate memory for the array of objects.
myVariable[i] = malloc(sizeof(struct Type)*THE_SIZE_IN_THE_OTHER_DIMENSION);
if ( myVariable[i] == NULL )
{
// Free everything that was allocated so far
for (int j = 0; j < i-1; ++j )
{
free(myVariable[j]);
}
free(myVariable);
// Exit the program.
exit(1);
}
}
However, if THE_SIZE_IN_THE_OTHER_DIMENSION is going to be 1, you are better off using your first approach.
struct Type* myVariable = malloc(sizeof(struct Type)*MY_SIZE);
// ^^^^^^^^^^^ Drop the *
if ( myVariable == NULL )
{
// Deal with error
exit(1);
}
Neither!
Use an idiom that reduces work and errors
pointer = malloc(sizeof *pointer * Number_of_elements);
Or in OP's case "to create an array of pointers in C"
#define ARRAY_N 100
struct Type **myVariable = malloc(sizeof *myVariable * N);
if (myVariable == NULL) Handle_OutOfMemmory();
Now set those pointers to some value
#define M 50
size_t i;
for (i=0; i<N; i++) {
myVariable[i] = malloc(sizeof *(myVariable[i]) * M);
if (myVariable[i] == NULL) Handle_OutOfMemmory();
for (size_t m = 0; m<M; m++) {
// Initialize the fields of
myVariable[i][m].start = 0;
myVariable[i][m].value = 0.0;
myVariable[i][m].set = NULL;
}
}

C Pointer and Memory Allocation: Realloc Arrays and Pointer Passing

For those experienced with C, this will be a simple memory allocation/referencing problem:
Here are my data structures:
struct configsection {
char *name;
unsigned int numopts;
configoption *options;
};
typedef struct configsection configsection;
struct configfile {
unsigned int numsections;
configsection *sections;
};
typedef struct configfile configfile;
Here are my routines for initializing a configsection or configfile, and for adding a configsection to a configfile:
// Initialize a configfile structure (0 sections)
void init_file(configfile *cf) {
cf = malloc(sizeof(configfile));
cf->numsections = 0;
}
// Initialize a configsection structure with a name (and 0 options)
void init_sec(configsection *sec, char *name) {
sec = malloc(sizeof(configsection));
sec->numopts = 0;
sec->name = name;
printf("%s\n", sec->name);
}
// Add a section to a configfile
void add_sec(configfile *cf, configsection *sec) {
// Increase the size indicator by 1
cf->numsections = cf->numsections + 1;
// Reallocate the array to accommodate one more item
cf->sections = realloc(cf->sections, sizeof(configsection)*cf->numsections);
// Insert the new item
cf->sections[cf->numsections] = *sec;
}
I believe my problem originates in my init_sec() function. Here is an example:
int main(void) {
// Initialize test configfile
configfile *cf;
init_file(cf);
// Initialize test configsections
configsection *testcs1;
init_sec(testcs1, "Test Section 1");
// Try printing the value that should have just been stored
printf("test name = %s\n", testcs1->name);
Although the printf() in init_sec() successfully prints the name I just stored in the configsection, attempting the same thing in the printf() of main() produces a segmentation fault. Further, addsec() produces a segmentation fault.
This routine should be
void init_file(configfile **cf) {
*cf = malloc(sizeof(configfile));
(*cf)->numsections = 0;
(*cf)->sections = NULL; // You forgot to initialise this.
}
i.e. called by init_file(&myconfigfilepointer); so the malloc return value gets passed back.
Need to do the same trick for init_sec
This function is incorrect - here is a corrected version
void add_sec(configfile *cf, configsection *sec) {
// Increase the size indicator by 1
// Reallocate the array to accommodate one more item
cf->sections = realloc(cf->sections, sizeof(configsection)*(1 + cf->numsections));
// Insert the new item
cf->sections[cf->numsections] = *sec; // Since arrays start at 0
cf->numsections = cf->numsections + 1;
}
You then need to adjust the calls in main
At no point do you initialise cf->sections, which means when you try to realloc it the first time, you're passing rubbish. Adding:
cf->sections = NULL;
to init_file should help.
You're also not checking any return codes, but you knew that yes?
You need to pass a pointer of the value to be updated... eg:
// Initialize a configfile structure (0 sections)
void init_file(configfile **cf) {
*cf = malloc(sizeof(configfile));
(*cf)->numsections = 0;
}
configfile *var;
init_file(&var);
printf("%d\n", var->numsections);
Otherwise you are just updating the local pointer *cf and not the original passed in value
You need to really rethink how function arguments are passed in C and what pointers are. Your problem has nothing to do with memory allocation. Rather, your code is assigning a pointer to dynamically allocated memory only to a local variable, of which the calling code knows nothing.
While you could solve the problem by passing a pointer to the caller's pointer (i.e. a double pointer), this is not necessarily the most elegant or most usual way of handling things. Rather, you should return the result of the allocation from the function. While you're at it, you should also use calloc to zero out the memory right away. Wrapping it all up:
typedef struct substuff_
{
int a;
double b;
} substuff;
typedef struct stuff_
{
unsigned int n;
substuff * data;
} stuff;
substuff * init_substuff()
{
substuff * const p = malloc(sizeof *p);
if (p) { p->a = 5; p->b = -0.5; }
return p;
}
stuff * init_stuff()
{
substuff * const p = init_substuff();
if (!p) return NULL;
stuff * const q = malloc(sizeof *q);
if (q) { q->n = 10; q->data = p; }
return q;
}
As an exercise, you should write the corresponding functions void free_substuff(substuff *) and void free_stuff(stuff *).
Yes, there is a problem in init_sec
// Initialize a configsection structure with a name (and 0 options)
void init_sec(configsection *sec, char *name) {
sec = malloc(sizeof(configsection));
sec->numopts = 0;
sec->name = name;
printf("%s\n", sec->name);
}
You're just copying the name pointer here, which means, that it points to the original storage of name. If you'd call init_sec like this
configsection foobar()
{
configsection sec;
char name[80];
get_name(name);
init_sec(sec, name);
return sec;
}
The name pointer became invalid the moment foobar returned. You need to duplicate the string and keep your private copy around. In init_sec:
sec->name = strdup(name);
But there's more. In the very first line of init_sec you're overwriting the pointer that was passed to init_sec with the one of malloc. So the new pointer never gets passed back to the calle. Either use a pointer to a pointer, don't take a configsection pointer at all (after all, you're allocating), but just return the allocated pointer: Complete corrected function:
// Initialize a configsection structure with a name (and 0 options)
configsection* init_sec(char *name) {
configsection *sec = malloc(sizeof(configsection));
sec->numopts = 0;
sec->name = name;
printf("%s\n", sec->name);
return sec;
}

Resources