How to assign a array to a pointer in a struct? - c

I have the following structs as example:
#define MAX_PEOPLE 16
typedef struct {
int age;
}Person;
typedef struct {
Person *people;
int numPeople;
}Team;
I'm trying to allocate an array of persons in a function, passed by parameters. My Team is supposed to store an array of 16 pointers of Person. I can't figure out what I'm doing wrong.
void initiateTeam(Team * team){
team->numPeople = MAX_PEOPLE;
Person *p[MAX_PEOPLE];
for(int i=0; i<MAX_PEOPLE;i++){
p[i] = malloc(sizeof(Person);
}
team->people = &p[0];
}
I printed out the addresses of my team->people[i] and I'm getting random junk. Why is the assingment team->people = &p[0] wrong? Shouldn't it get the first address of my array then perform pointer arithmetic?

You are pointing team->people to a statically defined array of person pointers. Once the function ends, the stack pointer moves back to where main left off, erasing all previously local memory in the addPeople function. You need to malloc p, and return it from the function

Since in the comments you stated that you're trying to allocate an array of Person objects and not pointers, you should rather do:
void addPeople(Team * team){
team->numPeople = MAX_PEOPLE;
team->people = malloc(sizeof(Person) * MAX_PEOPLE);
}
mind that there's no * in sizeof since you don't want an array of pointers but of objects. You will later be able to access the single elements (i.e. each Person object) with
team->people[2].age = 25; // The third person in the array
Finally, remember to free your memory.

your variable p is allocated in the stack of the addPeople() function. The assignment team->people = &p[0] (which is equivalent to team->people = p) is valid but dangerous because that address will be invalid as soon as the function is finished.
Better create p with malloc(sizeof (Person *) * MAX_PEOPLE) instead of using the stack.

The problem is here:
Person *p[MAX_PEOPLE];
This allocates a local variable in the function to hold the array of people pointers.
You get the address of this local variable and send it back. As soon as you are not in the function the local data is freed. It was just allocated locally. It is no longer valid. I might work for a while or it might not depending on the the program does next.
You want this:
Person **p = (Person **)malloc(sizeof (Person *) * MAX_PEOPLE);

I think you are getting the thing with pointer and memory management in C a little bit wrong. Consider reading a little bit more about it, before you continue coding your application.
Beside, I think you do not need an array of pointers to persons, but an array of persons.
Your struct is correct, but I would implement your function like that:
void addPeople(Team * team){
team->numPeople = MAX_PEOPLE;
team->people = malloc(sizeof(Person) * MAX_PEOPLE);
}
And do not forget to free() your team->people.
But if MAX_PEOPLE is an pre processor define, then it is totally unnecessary to use memory from the heap. If you are not storing too many people in your struct, the stack can easily fulfill your requirements.

Related

How to properly allocate and free memory from 2D array within array list within struct?

I am writing a program that has a bigger struct and a smaller struct, the smaller one holding names of friends of the person in index 0 of a 2D array in Friends. I wrote the whole thing from scratch a few times and it keeps giving me either seg fault or Thread 1: EXC_BAD_ACCESS (code=1, address=0x0).
Here are my structs:
expandBig() and expandFriends() do not assign values to the new data.
Looks like at least a problem is name assignment.
friends->name[friends->size] is not assigned a value after expandFriends(friends), so strcpy() fails.
void addFriend(Friends * friends, char * val) {
if(friends->size == friends->cap)
expandFriends(friends);
strcpy(friends->name[friends->size], val);
....
Consider using strdup()
// strcpy(friends->name[friends->size], val);
friends->name[friends->size] = strdup(val);
... and in InitializeFriends()
friend->name[i] = NULL;
Code such as below is tedious to review.
Was the size right? IDK, now have to trudge up to friend, find its type. OK that is Friends. Now look for Friends definition and see member char ** name. OK, now with char ** de-referenced we get char *. That matches codes sizeof(char*), so sizeof(char*) OK.
friend->name = realloc(friend->name, sizeof(char*) * friend->cap);
Save time. Code to the size of the de-referenced pointer, not the type. This is easier to code right, review and maintain.
Was the size right?
Yep, by construction, sizeof *(friend->name) is the right size.
// friend->name = realloc(friend->name, sizeof(char*) * friend->cap);
friend->name = realloc(friend->name, sizeof *(friend->name) * friend->cap);
// People * ret = (People*)calloc(DEFAULT_CAP, sizeof(People));
People * ret = calloc(DEFAULT_CAP, sizeof *ret);
Unclear why code sometimes casts the return from a *alloc() call and sometimes did not. The cast is not needed.

Segmentation fault on reallocating of memory

I need to make a program for bakery managment, I've done structures and three pointer arrays that must contain pointers for object of these structures. But i can't make function to add new bakery because it needs dynamic memory allocating. I've tried to do this but it throws Segmentation Fault on realloc. I would be grateful for any advice how to properly reallocate memory for these arrays to add element. Also feel free to make comments about other errors in the code, I'm just learning.
typedef struct BakeryType {
char *name;
} BakeType;
typedef struct Bakerys {
char *name;
BakeType *type;
char *photo;
float weight;
int portions;
float price;
char *description;
} Bakery;
Bakery *bakeryList[0];
BakeType *bakeTypeList[0];
void addBakery() {
Bakery new;
*bakeryList = realloc(*bakeryList, (sizeof(bakeryList)/ sizeof(Bakery))+ 1);//Segmentation Fault
bakeryList[sizeof(bakeryList)/sizeof(Bakery)]=&new;
}
bakeryList is a zero-element array of pointers to Bakery. It has room for zero pointers.
Yet later you set the first element of this array (*bakeryList which is the same as bakeryList[0]) to whatever comes back from realloc. So you're overwriting something, and it probably goes downhill from there.
I think you want bakeryList to just be a pointer to Bakery. That's how dynamically-allocated arrays work in C: you define a pointer to the first element and use pointer math (e.g., bakeryList[5] or *(bakeryList + 5)) to access other elements.
Another issue is your use of sizeof(bakeryList). sizeof is an operator that's evaluated by the compiler. It doesn't change at runtime. sizeof(bakeryList) / sizeof(Bakery) will evaluate to zero because you defined bakeryList as a zero-element array. You need another variable to keep track of how many elements are actually in the array at runtime.
Something like this would work:
int bakeryCount = 0;
Bakery *bakeryList = NULL;
void addBakery() {
// Add one to the array.
bakeryCount++;
bakeryList = realloc(bakeryList, bakeryCount * sizeof (Bakery));
// Create a pointer to the new element at the end of the array.
Bakery *newBakery = bakeryList + bakeryCount - 1;
// Set all the fields. Note that they will probably contain
// garbage so you should set them all.
newBakery->name = ...
}

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!

C - allocating values in an array of pointers in outside function

Lets say I have the following situation (some rough pseudocode):
struct {
int i;
} x
main(){
x** array = malloc(size of x pointer); // pointer to an array of pointers of type x
int* size = current size of x // (initally 0)
add(array, size);
}
add(x** array, int* size){ // adds one actual element to the array
x** temp = realloc(array, (*size)+1); // increase the array size by one
free(array);
array = temp;
// My question is targeted here
array[*size] = malloc(size of x); // makes a pointer to the value
array[*size]->i = size;
*size++;
}
My question is: Once add() is finished, do the values of the pointers stored in array disappear along with the function call stack, since I allocated them inside func()? I fear that they might, in which case would there be a better way for me to do things?
No, they don't. They persist until the pointer returned by malloc() is passed to the corresponding free() function. There would be no point in the existence of the malloc() function if it worked the same way as automatic arrays.
Edit: sidenote. As #Ancurio pointer it out, you're incorrectly freeing the memory behind the previous pointer returned by malloc() which is at that time invalid as realloc() has been used on it. Don't do that. realloc() does its job properly.)

Unexpected C struct pointer size behaviour

I have some odd behaviour going on in my code which seems to be resulting from the use of a generic pointer though really I am totally uncertain. I have a fairly standard struct which looks like the following:
typedef struct {
char* name;
PyAutoCFunc ac_func;
void (*func)();
PyAutoType type_id;
int num_args;
PyAutoType arg_types[MAX_ARG_NUM];
} func_entry;
static func_entry* func_entries;
I am storing a static pointer to an array of these struct elements which is allocated on the heap. At the point where I create a new element of this array and insert it, its values look like this...
func_entry new_fe;
new_fe.name = malloc(strlen(name) + 1);
strcpy(new_fe.name, name);
... // Init rest of struct
func_entries[num_func_entries] = new_fe;
num_func_entries++;
func_entry* fe = &func_entries[num_func_entries-1];
printf("Setting function '%s' at address '%p', name address '%p'\n", name, fe, fe->name);
This outputs.
>>> Setting function 'graphics_viewport_set_title' at address '0xfe2d40', name address '0xe40fe0'
Notice the size and value of fe->name. I then store this pointer into a hashtable to retrieve later. In the hashtable this is stored as a simple void*. Later when I retrieve the pointer from the hashtable an odd thing happens.
func_entry* fe = PyAutoHashtable_Get(func_table, c_func_name);
printf("Getting function '%s' at address '%p', name address '%p'\n", c_func_name, fe, fe->name);
Which outputs.
>>> Getting function 'graphics_viewport_set_title' at address '0xfe2d40', name address '0x6e6f74656c656b73'
The address of fe has clearly been in and out of the hashtable without issue, but the size and address of fe->name has changed. Even more weirdly is that fe->name is a different size to what it was before and even a different size to fe. Trying to access fe->name gives me a segfault and I am unsure how to proceed.
Out of interest this seems to occur when I use the code in an application with several linked libraries, I'm fairly sure all the code I'm running is 64 bit.
I have run the above code successfully in a separate application and get a correct pointer for fe->name (a smaller one).
I am also running on Ubuntu Linux 64 bit and compiling with gcc.
This is really where my C ignorance shines though as I imagine it could be a million things. Can anyone shine some light?
That address for name looks like the result of memory corruption. It's completely unaligned, which is unlikely for an address returned by strdup off the heap.
It looks like you're out of scope for the structure you created. You mentioned it's created on the heap, but in the code it looks like it's probably created on the stack. This isn't all being done in the same function, is it? Is the code in the first block in a function that's existed before running the code in the later block? As soon as you exit that function the memory for that structure ceased to be, even though you retained a pointer to it. Later, when you pulled the pointer out of the hash table the memory had been overwritten and didn't have the pointer to name there anymore. If you're going to pass around pointers to structures allocate them dynamically by using malloc. They're exist until you explicitly get rid of them using free, instead of when the function ends.
Pointers always are of the same size whether its a pointer to a struct or a generic pointer (char * in olden days, void * in ANSI standard.)
Here's a simple example I whipped out so that you could understand structures, pointers (not in detail though but you get the idea.)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct person {
char *name;
int age;
};
void print(void *);
int main()
{
struct person *david;
if ((david = (struct person *)malloc(sizeof(struct person))) != NULL) {
david->name = strdup("David");
david->age = 40;
printf("sizeof david = %d, sizeof person = %d\n", sizeof david,
sizeof(struct person));
print((void *)david);
}
}
void print(void *p)
{
struct person *pp = (struct person *)p;
printf("sizeof p = %d, sizeof pp = %d\n%s %d\n", sizeof p, sizeof pp,
pp->name, pp->age);
}
Output
sizeof david = 8, sizeof person = 16
sizeof p = 8, sizeof pp = 8
David 40
Hope that helps.
It certainly looks as if something is writing over that data structure. The pointer value 0x6e6f74656c656b73 which you are seeing looks very suspicious indeed - it is ASCII for "noteleks", which is "skeleton" backwards. Perhaps this might give you an idea of what is overwriting your data.

Resources