Array object pointers with string assignment causes crash - c

So I am trying to assign a string value to an object in an array.
The object code is:
typedef struct BiTreeData_ {
char* word;
int start_word_count;
int end_word_count;
int start_ranking;
int end_ranking;
} BiTreeData;
In my main I make an array of pointers to BiTreeData using:
BiTreeData **dataarray;
dataarray=(BiTreeData**)malloc(sizeof(BiTreeData*)*maintree.size);
I try to assign a value to one of the variables within the struct with:
int z = dataarray[i]->start_word_count;
The program crashes. Any help would be appreciated. Thank you.

Your code here
BiTreeData **dataarray;
dataarray=(BiTreeData*)malloc(sizeof(BiTreeData)*maintree.size);
allocates the memory space for an array of BitTreeData* but you are not allocating any space for the BitTreeData objects themselves. You just have a dynamic array of pointers that point to uninitialised memory.
It would probably be far easier if you just create an array of BitTreeData rather than of pointers. You could achieve this by using
BiTreeData *dataarray;
dataarray=(BiTreeData*)malloc(sizeof(BiTreeData)*maintree.size);
This just creates an array of BitTreeData - you can then access each item in the array like you would any other array (remembering now that the array is of BitTreeData not BitTreeData*)

you have to allocate memory for each element in the array of dataarray
dataarray[i] = (BiTreeData *) malloc ((sizeof(BiTreeData)
the followingline code you put
array=(BiTreeData**)malloc(sizeof(BiTreeData*)*maintree.size);
with this code, you have allocated array of pointers. but theses pointers are not pointed to any content yet. so you have to allocate memory for each pointer in the array

Is there a reason you are defining
BiTreeData **dataarray;
To get this to work the way you want I think you need to define it as:
BiTreeData *dataarray;
This will allow you to malloc an array of BiTreeData structs.
To create the array of structs:
BiTreeData *dataarray;
To allocate memory on the heap for the array of structs:
dataarray = malloc(sizeof(BiTreeData)*maintree.size);
To set the value of a struct element in your array:
int z = 5;
dataarray[i].start_word_count = z;
To extract a value from your struct array:
int z = dataarray[i].start_word_count;

Since you're allocating an array of pointers, the size of element should be the size of BiTreeData *, not BiTreeData:
dataarray= (BiTreeData **)malloc(sizeof(BiTreeData *) * maintree.size);
EDIT
The question has since been edited to correct this mistake.

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.

Different arrays in dynamic struct, creation, writting, reading

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!

Passing an Array of Structures

How can I pass an array of structures?
So far I have this which is global:
typedef struct _line
{
float val1;
int val2;
} line;
Then I read data from a file into this structure
struct _line* read_file()
{
typedef struct _line *Lines
Lines *array = malloc(num_lines * sizeof(Lines));
//read values into structures here
Then I fill up the structures in the array with values. If I do printf("%d", (*array[1]).val1); I get the right value here in this particular method
Then I return the array like so
return *array
But when I do so, only the 0th structure reads correctly in the method I returned to. Reading the 1st element just prints random values. What am I doing incorrectly?
You should not dereference the array when you return it1, it's actually of incompatible type with the function return type, just
return array;
also, check that array != NULL after malloc() before reading the values, and you don't really need the typedef it makes your code a bit confusing.
If your code compiled which I doubt, then you don't have warnings enabled in your compiler command, enable them so you can prevent this kind of issue.
(1) *array is equivalent to array[0].
Expanding on my comments, your code (as you describe and show it) you have undefined behavior:
This is because you allocate an array of pointers, but you apparently do not allocate the pointers in that array. So when you dereference a pointer (which you haven't allocated and whose value is indeterminate and so will point to a seemingly random location) you have this undefined behavior.
Instead of using a type-alias like Line use the structure name, like
struct _line *array = malloc(num_lines * sizeof(*array));
That will allocate num_lines structures (instead of pointers), then you use it like a normal array, without the pointer dereferencing
array[x].val1 = something;
And you of course return that pointer array as-is:
return array;

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.

C: Dynamic array of pointers to array of structure

I have a structure and a bidimensional array of those structs:
typedef struct {
char exit_n;
char exit_s;
char exit_w;
char exit_e;
} room;
room map[MAP_WIDTH][MAP_HEIGHT];
I need an array of pointers those structs. The following code compiles, but I don't get the wanted result. Any help? This is getting really confused to me, any explanation would be appreciated
room *rooms;
rooms = (room*)malloc(sizeof(room*) * ROOM_NUM);
[..]
rooms[n] = map[room_x][room_y];
[..]
Actually, I think you want
room** rooms;
rooms = (room**)malloc(sizeof(room*) * ROOM_NUM);
[..]
rooms[n] = &map[room_x][room_y];
This gives you an array of pointers to your rooms.
I'm am pretty sure you want
sizeof(room)
You need to allocate enough space for the struct. You are only allocating for a pointer.
You also may need to allocate differently if you want a 2D array:
see here dynamic allocating array of arrays in C
The major issue I see is that you are using sizeof(room*). This means that you are taking the size of a pointer to a structure, which is not what you want. You want to allocate the size of the structure, so make that sizeof(room). Also, use calloc in this case, not malloc, as you are basically implementing the former's functionality by multiplying the number of rooms by the size of the room.
In your current code, rooms becomes an array of room structures, not an array of pointers. If you want an array of pointers that each point to your map array, you need another layer of indirection:
room** rooms = malloc(ROOM_NUM * sizeof *rooms);
// ...
rooms[n] = &map[room_x][room_y];
(Or you can use sizeof (room *) like your code has instead of sizeof *rooms; I prefer to write it that way to avoid duplicating type information.)
You need to allocate space for the pointers and for the rooms and then initialize the pointers to point to the rooms.
room *rooms;
room **prooms;
rooms = (room*)malloc((sizeof(room) + sizeof(room*)) * ROOM_NUM);
prooms = (room**)(&rooms[ROOM_NUM]);
for (int ii = 0; ii < ROOM_NUM; ++ii)
prooms[ii] = &rooms[ii];
If I understand correctly, you want an array of pointers to all the room values in map. Since there are MAP_WIDTH*MAP_HEIGHT such values, we need that many pointers:
room *rooms[MAP_WIDTH*MAP_HEIGHT];
The above declares rooms as an array of pointers.
Now, to assign the values:
size_t i;
size_t j;
for (i=0; i < MAP_WIDTH; ++i)
for (j=0; j < MAP_HEIGHT; ++j)
rooms[i*MAP_HEIGHT+j] = &map[i][j];
We basically find the address of each element in map, and store it in the correct entry in rooms.
Is this what you wanted?

Resources