Writing to array of pointers in C - c

I need to write the pointer address of a struct (struct is called "Post") that has reposted another Post. There's a fixed return type called result with the following declaration:
struct result {
void** elements;
size_t n_elements;
};
For the Post struct, it has the following declaration:
struct post {
uint64_t pst_id;
uint64_t timestamp;
size_t* reposted_idxs;
size_t n_reposted;
};
Here's my code:
result* find_all_reposts(post* posts, size_t count, uint64_t post_id, query_helper* helper) {
result * ret_result = (result *) malloc(sizeof(result));
ret_result->elements[100];
ret_result->n_elements = 0;
for(int i = 0; i < count; i++){
post * temp = &posts[i];
size_t total_reposted = temp->n_reposted;
if(total_reposted > 0){
for(int q = 0; q < total_reposted; q++){
int index_of_repost = temp->reposted_idxs[q];
ret_result->elements[q] = &posts[index_of_repost];
ret_result->n_elements++;
}
}
}
return ret_result;
}
However I get a SEGV error for ret_result->elements[q] = &posts[index_of_repost];. I thought it could be originally that I hadn't initialised the elements field in the ret_result struct but I receive warning: statement with no effect for that:
warning: statement with no effect [-Wunused-value]- ret_result->elements[100];
I'm thinking that the void ** type for the elements field in result might be messing me around. From what I understand that's a pointer to a pointer which can obviously be an array and hence is basically a pointer to an array of posts?
I should clarify that count is the number of posts and that the returned-result is managed separately and hence any heap-allocated memory is freed in a separate process.
Thanks for your help :)

You haven't initialized ret_result->elements to anything. The statement ret_result->elements[100] is a no-op, the only reason you're not segfaulting there too is because your compiler is cutting it out. If you want that field to be a pointer to an array of size 100 you must initialize it with malloc. I'm not sure why you're declaring it to be a void ** double pointer here, but if it must be that way then something like this might work:
ret_result->elements = malloc(100 * sizeof(struct post *));
The call's arguments could also be 100 * sizeof(void *), but it might be a little what you intend to store there if you specify the struct to which the data will be pointing.

Related

What is the difference between initializing struct in following ways in C?

I am learning c. I have an struct that looks like below. I see 2 different ways of initializing the struct variable. It would be great, if someone could explain what is the difference between these 2 ways & which one is preferred in which case.
typedef struct {
int length;
int* elements;
} Array;
Array create_array_type_one(int size) {
Array result;
result.length = 0;
result.elements = (int *)malloc(size * sizeof(int));
return result;
}
Array* create_array_type_two(int size) {
Array *array = (Array *) malloc(sizeof(Array));
array->length = 0;
array->elements = (int *) malloc(sizeof(int) * size);
return array;
}
So, here we are talking about STRUCTURES & FUNCTIONS.
Basically there are three methods by which invoker and invoked structure function can communicate to each other.
Passing each member of the structure as an actual argument of the function call, or returning to the each member type.
Sending the copy of the structure to the entire called function or returning to the struct type (call by value).
Using pointers, pass the structure as an argument and indirectly work on the original structure or returning the address of the struct (call by reference).
Your, CASE 1:
Array create_array_type_one(int size) {
Array result;
result.length = 0;
result.elements = (int *)malloc(size * sizeof(int));
return result;
}
In this case you are returning a copy of the entire structure to the calling function. So, in order to use it in your main() function, you should do something like this:
Array new;
new = create_array_type_one(5);
Here, you are assigning the returned structure of type Array to a structure of type Array.
In CASE 2:
Array* create_array_type_two(int size) {
Array *array = (Array *) malloc(sizeof(Array));
array->length = 0;
array->elements = (int *) malloc(sizeof(int) * size);
return array;
}
In this case you are using pointers and returning a pointer to the newly created data structure of type Array. You are not sending a copy of the structure to the calling function instead you are sending its address to the calling function. Therefore, what happening in the main() while calling like this is:
Array *ptr;
ptr = create_array_type_two(5);
Both cases has there own advantages and disadvantages like CASE 1 ensures data safety as all the work done by the called function happens on a copy but uses extra memory. Where CASE 2 is more efficient and faster as compared to the previous method, as it uses same memory location for the operation.
The difference of them is the return type.
create_array_type_one() returns Array type memory location.
create_array_type_two() returns a pointer to Array type memory location.
As Array type has only two elements, int and int *, the size difference between two of them is not big . So you can use anyone for your coding preference in this case.
I'd like to recommend you the second one if the size of structure is kind of big...

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

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.

Manipulating dynamic array using realloc in a function

Using what I have learned here: How to use realloc in a function in C, I wrote this program.
int data_length; // Keeps track of length of the dynamic array.
int n; // Keeps track of the number of elements in dynamic array.
void add(int x, int data[], int** test)
{
n++;
if (n > data_length)
{
data_length++;
*test = realloc(*test, data_length * sizeof (int));
}
data[n-1] = x;
}
int main(void)
{
int *data = malloc(2 * sizeof *data);
data_length = 2; // Set the initial values.
n = 0;
add(0,data,&data);
add(1,data,&data);
add(2,data,&data);
return 0;
}
The goal of the program is to have a dynamic array data that I can keep adding values to. When I try to add a value to data, if it is full, the length of the array is increased by using realloc.
Question
This program compiles and does not crash when run. However, printing out data[0],data[1],data[2] gives 0,1,0. The number 2 was not added to the array.
Is this due to my wrong use of realloc?
Additional Info
This program will be used later on with a varying number of "add" and possibly a "remove" function. Also, I know realloc should be checked to see if it failed (is NULL) but that has been left out here for simplicity.
I am still learning and experimenting with C. Thanks for your patience.
Your problem is in your utilisation of data, because it points on the old array's address. Then, when your call realloc, this area is freed. So you are trying to access to an invalid address on the next instruction: this leads to an undefined behavior.
Also you don't need to use this data pointer. test is sufficient.
(*test)[n-1] = x;
You don't need to pass data twice to add.
You could code
void add(int x, int** ptr)
{
n++;
int *data = *ptr;
if (n > data_length) {
data_length++;
*ptr = data = realloc(oldata, data_length * sizeof (int));
if (!data)
perror("realloc failed), exit(EXIT_FAILURE);
}
data [n-1] = x;
}
but that is very inefficient, you should call realloc only once in a while. You could for instance have
data_length = 3*data_length/2 + 5;
*ptr = data = realloc(oldata, data_length * sizeof (int));
Let's take a look at the POSIX realloc specification.
The description says:
If the new size of the memory object would require movement of the object, the space for the previous instantiation of the object is freed.
The return value (emphasis added) mentions:
Upon successful completion with a size not equal to 0, realloc() returns a pointer to the (possibly moved) allocated space.
You can check to see if the pointer changes.
int *old;
old = *test;
*test = realloc(*test, data_length * sizeof(int));
if (*test != old)
printf("Pointer changed from %p to %p\n", old, *test);
This possible change can interact badly because your code refers to the "same" memory by two different names, data and *test. If *test changes, data still points to the old chunk of memory.

Run through a structure and print all the values?

I have a pointer to a structure and I'd like to fetch all of its members by trial and error. I'm trying to run through the structure by incrementing the pointer by one and derefencing it. It should return a correct value from the structure (every i*sizeof(int) time) but it doesn't.
What am I doing wrong?
fn (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
{
/*
assume that all struct members are int types
typedef struct
{
mach_msg_bits_t msgh_bits;
mach_msg_size_t msgh_size;
mach_port_t msgh_remote_port;
mach_port_t msgh_local_port;
mach_msg_size_t msgh_reserved;
mach_msg_id_t msgh_id;
} mach_msg_header_t;
size of the struct is 24.
*/
printf("ID: %d \n",InHeadP->msgh_id); //prints 'ID: 1337'
printf("Ptr: %p\n",InHeadP);
for (int i = 0; i <= 24; i++)
{
int deref = *((int*)(InHeadP+i));
printf("InHeadP[%d]=%d\n",i,deref);
//no sign of 1337 anywhere
}
}
P.S. I know that I shouldn't be doing that, but this is only for testing purposes.
Because InHeadP is a mach_msg_header_t*, adding an integer to it will actually add that integer times sizeof(mach_msg_header_t), as though you were indexing an array of mach_msg_header_ts (and is actually how array indexing works). You need to cast InHeadP to an int* before performing arithmetic on it, and even then, as the struct has six fields, i should only go up to 6, not 24.
A preferred method to iterate through a structure is to create a function that returns the value or address of the field given an index. Note that if the order of the members in the struct changes, this function must change too:
int * Index_Of(unsigned int index, mach_msg_header_t * p_struct)
{
switch (index)
{
case 0: return (int *) &(p_struct->msgh_bits);
case 1: return (int *) &(p_struct->msgh_size);
case 2: return (int *) &(p_struct->msgh_remote_port);
case 3: return (int *) &(p_struct->msgh_local_port);
case 4: return (int *) &(p_struct->msgh_reserved);
case 5: return (int *) &(p_struct->msgh_id);
}
return 0;
}
Just remember that treating the structure as contiguous fields (members) is not advisable since the compiler is allowed to add padding between structure members. Thus any method to access the fields except by name, is dangerous and will lead to very difficult bugs.
BTW, treating each field as an int is also dangerous. If any of the types is changed to something else, like a double, your code will break. Compiler will not catch the error because casting tells the compiler YOU know what you are doing.
You could "turn the picture around" and implement a Visitor pattern:
struct Visitor_Void
{
void (*fn_msgh_bits)(mach_msg_bits_t);
void (*fn_msgh_size)(mach_msg_size_t);
void (*fn_msgh_remote_port)(mach_port_t);
void (*fn_msgh_local_port)(mach_port_t);
void (*fn_msgh_reserved)(mach_msg_size_t);
void (*fn_msgh_id)(mach_msg_id_t);
};
void Visit_Members(mach_msg_header_t * p_header,
struct Visitor_Void * p_visitor)
{
(p_visitor->fn_msgh_bits)(p_header->msgh_bits);
(p_visitor->fn_msgh_size)(p_header->msgh_size);
(p_visitor->fn_msgh_remote_port)(p_header->msgh_remote_port);
(p_visitor->fn_msgh_local_port)(p_header->msgh_local_port);
(p_visitor->fn_msgh_reserved)(p_header->msgh_reserved);
(p_visitor->fn_msgh_id)(p_header->msgh_id);
return;
}
No, you shouldn't be doing this!
What is particularly wrong here
for (int i = 0; i <= 24; i++)
{
int deref = *((int*)(InHeadP+i));
printf("InHeadP[%d]=%d\n",i,deref);
}
is that you print the first int of 24 different structs.
When you call (int*)(InHeadP+i) you are doing pointer arithmetic on mach_msg_header_t which is size 24. So your first iteration is at the beginning of the struct, and your second iteration is right after your struct. You are accessing some other memory.
Try (((int*)InHeadP)+i).
Wait a second, this is wrong:
int deref = *((int*)(InHeadP+i));
You want
int deref == *((int*)InHeadP+i)
You skipping 24 bytes each time through the loop, rather than 4.

Resources