Different arrays in dynamic struct, creation, writting, reading - c

Strait to the point.
I have a struct with a string, char and int.
The struct is created dynamically because i will need it in different parts of my program.
struct A
{
char staticString[20];
char* dynamicString;
char character;
int integer;
};
I know if i want to create a struct i call:
A example = (A)malloc(sizeof(A));
In order to populate the dynamicString and int i used:
example->dynamicString = (char*)malloc(sizeof(char*));
example->integer = (int)malloc(sizeof(int));
Unfourtanetly when i tried to populate staticString and char it didn't worked.
Don't even ask what was my code for those, i tried a lot of combinations from everywhere.
In addition to that can somebody show me examples how to write/read those values?
Thanks in advance.

First things first:
You're using C, and by the way you've defined the structure, you need to declare the pointer like so:
struct A *example;
Next, malloc returns a pointer, so you need to cast to a pointer (and not to a structure):
(struct A *)malloc(sizeof(struct A));
Secondly, I'm not sure why but hey:
- you're trying to dynamically allocate an int in the structure. As I said previously, malloc returns a pointer, so in your structure you need an int pointer like so "int *integer;"
- you're trying to allocate a dynamic string, however you're not doing it properly, here is what I think you want
example->dynamicString = (char *)malloc(sizeof(char) * 10);
Where 10 is the size of your dynamic string.
Edit:
you may also populate the integer in your struct statically or dynamically, but I think you intended the static approach:
example->integer = 123;
The dynamic approach would be (assuming you have int *integer in your struct):
example->integer = (int *)malloc(sizeof(int));
*(example->integer) = 123;

Every time you create a new struct the memory in the heap is set to size of :
sizeof(char)*20 + sizeof(char pointer) +sizeof(char)+ sizeof(int).
If you want to save a string that will be pointed to by your char pointer- then you ask for allocation in heap for the size of that string- and malloc returns the pointer to that memory allocation on heap.
So, you already have a space for your char array, char pointer, char and int that was allocated when you asked to make a new struct and do not need to allocate it again.
also, keep in mind malloc returns a pointer to the allocated place on the heap- so if you malloc(sizeof(int)) you get a pointer to a memory allocation for an int on the heap- which is pointed to by a int pointer Not an int.
good luck!

Related

Free pointer to an array

In my program I have a structure that looks like this:
struct structure {
int n;
int *arr;
};
And I allocate memory for arr like this:
structure->arr = malloc(sizeof(int) * arr_size);
Now here is where I start to get confused, and I am not sure if I am doing it right. What I want to do is use "arr" as an array to store or access integers. So I set arr to point to an array that I created and filled with 0's:
int new_arr[i];
structure.arr = new_arr;
I am not sure if this is right, but so far I don't get any errors. So I create another array that stores these structures, and I insert some new structures in it. But when I try to free the member arr from any of the structures inside the array (like this free(&array_of_struct[i].arr);) I get an error:
==747==ERROR: AddressSanitizer: attempting free on address which was not malloc()-ed: 0x7fffd7c6ad08 in thread T0
SUMMARY: AddressSanitizer: bad-free (/lib/x86_64-linux-gnu/libasan.so.5+0x10d7cf) in __interceptor_free
==747==ABORTING
So I think I understand what the problem is, but I have no idea how to solve it. I don't imagine this is the way I'm supposed to point to an array, so can anyone tell me how to do it right?
UPDATE
So instead of writing "structure.arr = new_arr" I am now using memset this way:
memset(structure.arr, '\0', array_size * sizeof(int));
But I still get the same arror when trying to free structure.arr. Also if I try to use mempcy. Could there be something wrong with free(&array_of_struct[i].arr)?
UPDATE2
So I actually managed to use mempcy and free member "arr". The problem is, that I can only do it before I append the structure to my array of structures. If I try to free it after that (as a member of the array) I get the errors.
LAST UPDATE
I have managed to make it work with memset. The problem was that I had to write free(array_of_struct[i].arr) instead of free(&array_of_struct[i].arr)
Thank you all for the help.
Don't do this:
structure.arr = new_arr;
That's not a copy of array content. That simply reassigns the pointer.
That means you are replacing the pointer with an allocation from somewhere else. At best, you'll have a memory leak from not freeing the original allocation. At worst, you'll crash because you attempt to free new_arr which is a stack array (invalid to invoke free on that address).
Do this instead, copy the array contents instead of overwriting the pointer:
memcpy(structure.arr, new_arr, arr_size * sizeof(int));
But if you just want to "zero out" the original allocation (as you implied), you just need to do this:
memset(structure.arr, '\0', arr_size * sizeof(int));
Or just use calloc instead of malloc to allocate and zero-out the contents at the same time.
structure->arr = calloc(arr_size, sizeof(int));
Update
But I still get the same arror when trying to free structure.arr. Also if I try to use mempcy. Could there be something wrong with free(&array_of_struct[i].arr)?
You need to pass to free exactly what was assigned from malloc.
So instead of this:
free(&array_of_struct[i].arr);
This:
free(array_of_struct[i].arr);
int *p = malloc(size);
int arr[size];
p = arr; // Not good. The memory we allocated above is now lost.
free(?); // We don't have a pointer to the allocated memory
int *p = malloc(size);
int arr[size];
int *q = arr;
p = arr; // Ok, because we have saved the pointer so we can free later
free(q);
int *p = malloc(size);
int arr[size];
memcpy(p, arr, size * sizeof *p);
free(p); // Works fine. We have not overwritten the pointer
You get this error since you can free only memory that was malloc'd.
when you write int new_arr[SIZE] you allocate the array on the stack, so you don't need to free it (you can say it will be "freed" when you leave the function in which you allocated it).
As for your struct, if you're aiming for an array that has a constant size that you know in advance, I would recommend that you implement it like this:
struct my_struct {
int arr[SIZE];
}
This will allocate the array as part of the struct (in my opinion this is more readable). So when you define an instance of this struct in your program it's sufficient to write:
struct my_struct s;
and the array will be allocated as well. In this case, you won't need to free it since you won't malloc it.
If you don't know the size of the array in advance, then it would be better to first allocate the memory using malloc and then use memcpy like #selbie suggested.

malloc'ing for field inside struct

I have, roughly speaking, a function prototype like this:
init_superstruct(const char *name, Superstruct **super, int num_substructs) {...
where superstruct looks like
typedef struct superstruct {
char *name,
Substruct **substructs,
int num_substructs;
} Superstruct
The function is supposed to
1) allocate memory for (and initialize) super, by...
2) ...assigning the name field of super enough memory to hold the name argument, and...
3) ...assigning the substructs field enough memory to hold an array pointers to Substructs (of size num_substructs).
My question: will the following code accomplish these goals?
*super = malloc(sizeof(*super));
*super->name = malloc(sizeof(strlen(name) + 1)));
*super->substructs = calloc(num_substructs, sizeof(Substruct));
This is literally my first foray into dynamic memory allocation. Any advice you have would be helpful for me!
First:
*super = malloc(sizeof(*super));
You want sizeof(**super). *super is a pointer, with type Superstruct *, so this won't allocate enough memory.
Really, you should probably allocate the structure normally, then assign it to the pointer separately. This will make your code much easier to write:
Superstruct *r = malloc(sizeof *r);
r->name = …
*super = r;
Second:
*super->name = malloc(sizeof(strlen(name) + 1)));
This is wrong. sizeof(strlen(name) + 1) is sizeof(int) (or perhaps sizeof(size_t); either way it's not what you want) -- strlen() won't even be called! Remove the sizeof() from this expression to make it correct.
Third: to allocate a single array of Substruct objects, define the structure member as Substruct *substructs, and allocate it using the exact code you've got right now. You don't need a double pointer unless you want an array of pointers to the structures, which is more complicated than you need.
If you really think you do need an array of pointers here (you probably don't), you need to allocate the array using sizeof(Substruct *) as the size argument to calloc(), not sizeof(Substruct).

How to use a pointer to character within a c structure?

It is possible to declare a string of the required size using char name[size], however if I want to use char *name, how will I specify the size that I require using malloc()?
I found out that I cannot use char *name = malloc(5*1); within the structure declaration.
I have tried using
struct data
{
int age;
char *name;
};
On running this code and entering the string I encountered Segmentation fault.
How must I specify the size?
You need to specify the size of the pointer, you need to make the pointer to point to a valid memory, that's all. Moreover, it not necessary to use malloc(). You can either
allocate memory to the pointer via allocator functions, malloc() or family
make the pointer point to the address of any other char variable (or array)
To elaborate, you create a variable var of type struct data, and then, make var->name point to a valid chunk of memory.
That said, to use malloc() for allocating required size of memory, you need to supply the required size as the argument to malloc() (in bytes).
let's say you create a variable a of the type struct data
struct data a;
Now allocate memory to the name member of a i.e,
a.name = malloc(size_of_name + 1); //+1 for '\0' character at the end
Now you can use a.name to store and use the string
Don't forget to free the allocated data before terminating the program. for this use free(a.name).
You need to allocate the memory like:
data* r = malloc(sizeof(data));
r->name= malloc(20);
assuming the name can hold 20 chars
You'd need to supply a way to initialize your structure. For example:
void init_data (struct data *p_data) {
if (p_data)
p_data->name = malloc(STR_LEN);
}
And you should couple that with a function to free the memory:
void release_data (struct data *p_data) {
if (p_data)
free(p_data->name);
}
It would than be called whenever you want to use your structure.
struct data d;
init_data(&d);
/* use d */
release_data(&d);

Declare and allocate memory for an array of structures in C

I'm trying to declare and allocate memory for an array of structures defined as follows:
typedef struct y{
int count;
char *word;
} hstruct
What I have right now is:
hstruct *final_list;
final_list = calloc (MAX_STR, sizeof(hstruct));
MAX_STRbeing the max size of the char word selector.
I plan on being able to refer to the it as:
final_list[i].count, which would be an integer and
final_list[i].word, which would be a string.
ibeing an integer variable.
However, such expressions always return (null). I know I'm doing something wrong, but I don't know what. Any help would be appreciated. Thanks.
A struct that contains a pointer doesn't directly holds the data, but holds a pointer to the data. The memory for the pointer itself is correctly allocated through your calloc but it is just an address.
This means that is your duty to allocate it:
hstruct *final_list;
final_list = calloc(LIST_LENGTH, sizeof(hstruct));
for (int i = 0; i < LIST_LENGTH; ++i)
final_list[i].word = calloc(MAX_STR, sizeof(char));
This requires also to free the memory pointed by final_list[i].word before releasing the array of struct itself.

how to convert a dynamically numerical string into a dynamically array of integers

struct integer* convert_integer(char* stringInt)
{
struct integer* convertedInt_1;
char* stringArray3 = (char *) malloc (sizeof(char));;
free(stringArray3);
stringArray3 = stringInt;
convertedInt_1->digits = atoi(stringArray3);
stringArray4 = stringInt;
}
this is a sample of the code. this code is giving me an error when i use the standard library from c "Warning: assignment makes pointer from integer to without a cast"
so i need to know how to convert a dynamically numerical string into dynimacally struct integer
You do not need any dynamic allocation for char string here, nor do you need an additional char * pointer.
struct integer* convert_integer(char* stringInt)
{
/*Allocate memory to structure,You cannot return pointer to local structure*/
struct integer* convertedInt_1 = (struct integer*)malloc(sizeof(*convertedInt_1));
/*Convert the string to integer*/
int i = atoi(stringInt);
/*Assign converted integer to structure member*/
convertedInt_1->digits = i;
/*return pointer to heap allocated structure*/
return convertedInt_1 ;
}
There are a lot of problems with this code, but I'll try to walk you through them.
One, you malloc only one char worth of memory, not the amount of memory needed to hold your array. You really need to include an argument for the size of the array to be changed if the string is not null terminated.
Second, you're trying to use memory after you free it. This is bad. Very bad. You should only free memory after you're finished with it.
Next, you're trying to atoi the entire array at once. This is going to try to change the entire string into one number, not one int.
What I think you want, is to convert each character from stringInt to a (single digit) int in your result. For this, use a for loop to iterate through the array.
I'm pretty sure you want to be using int and not integer.
Last, you forgot to return anything - this doesn't compile.

Resources