I was looking forward to make an array of struct just like [ obj, obj, obj ].
I got this struct:
struct obj {
char name[MAX_NAME];
char desc[MAX_TEXT];
bool asible;
};
How can I make it?
I tried
struct obj **objInRoom = malloc(sizeof(struct obj));
But when I iterate in it, it doesnt have anything :D
I chose this solution because I need to put that array of struct into this struct:
struct room {
struct obj **objts; //HERE
int qntty_objts;
struct interact **interacts;
int qntty_interacts;
};
If you need to have a double pointer for some reason, then you can do something like this struct obj *objInRoom = malloc(sizeof(struct obj)); and then assign address of objInRoom to your struct room->objts=&objInRoom.
struct obj **objInRoom = malloc(sizeof(struct obj));
If I simplifies, in your try you are allocating an area for a struct and trying to assign its address to a 'struct obj address' address holder which is struct obj**. But you should use struct obj * to hold the address of newly allocated area.
Which in this case your struct room should be like this:
struct room {
struct obj *objts; //struct obj** to struct obj*
int qntty_objts;
struct interact **interacts;
int qntty_interacts;
};
You should assign your newly allocated area like this:
struct obj *objInRoom = (struct obj*)malloc(sizeof(struct obj));
But in this case you only allocated the area for one struct obj element. To increase this area you can take the backup of your previous data and allocate new area for more size. For example to increase your allocated area two times:
//cap is integer defined before to hold capacity information of array
struct obj *backup = (struct obj*)malloc(2*cap*sizeof(struct obj));
for(int i = 0; i < cap; ++i)
backup[i] = objInRoom[i];
free(objInRoom); //to prevent memory leak, because we allocated new area for our incremented sized array.
objInRoom = backup;
cap *= 2;
Or you can simply use realloc to increase your array capacity if an allocation happened before with malloc or calloc, realloc creates an array with desired size and holds the previous data:
objInRoom = (struct obj*)realloc(objInRoom, 2*cap*sizeof(struct obj))
Note: Always cast your malloc operation to your desired pointer type because it returns 'void *' for default.
Note 2: Always check outputs from malloc, realloc and calloc; they return NULL in case of error.
Related
I'm trying to allocate memory for a pointer, but have a reference to the address of that pointer. I'm still pretty new to C and this is my first time working with double pointers really.
So I have two structures and they look like this:
typedef struct myNodes {
int data;
struct myNodes *next;
} listElement;
typedef struct {
listElement **ptrToElements;
} myStruct;
In another file, I'm trying to dynamically allocate memory for my pointer by doing something like this:
myStruct *myStruct = malloc(sizeof(*myStruct));
*(myStruct->ptrToElements) = (listElement*)malloc(sizeof(listElement));
but I keep encountering a segmentation fault from doing so. What could be the issue? Thanks!
The problem is with
*(myStruct->ptrToElements) ....
statement. Before dereferencing myStruct->ptrToElements, you need to make sure it points to a valid memory.
To elaborate, you allocate memory for myStruct. Fine.
That constitutes allocating memory for the member ptrToElements. Good.
Question: What does ptrToElements points to?
Answer: Indeterministic.
So, when you try to derefernce a pointer which points to an indeterministic memory address, it's pretty much invalid memory address and attempt to do so will invoke undefined behavior.
Solution: You need to allocate memory for myStruct->ptrToElements before you can go ahead and dereference it.
having said that, please see do I cast the result of malloc?
You define the structure to contain a pointer to a pointer to a listElement
typedef struct {
listElement **ptrToElements;
} myStruct;
As Sourav Ghosh wrote, you try to assign a value to the pointer where ptrToElements would point to without allocating memory.
Probably you should change the pointer type to
typedef struct {
listElement *ptrToElements;
} myStruct;
and when allocating the memory
myStruct *myStruct = malloc(sizeof(*myStruct));
/* If the list can be empty, initialize root with NULL pointer */
myStruct->ptrToElements = NULL;
/* when you add the first list element */
myStruct->ptrToElements = malloc(sizeof(listElement));
myStruct->ptrToElements->data = someValue;
/* at least for the last element you add here you should initialize next */
myStruct->ptrToElements->next = NULL;
Don't forget to handle errors, e.g. malloc returning NULL.
I think this is what you want:
typedef struct myNodes {
int data;
struct myNodes *next; // not clear what this pointer is used for...
} listElement;
typedef struct {
listElement *ptrToElements;
} myStruct;
// Memory Allocation
// allocate myStruct pointing to an array of N listElements
myStruct *ms = malloc(sizeof(myStruct));
ms->ptrToElements = malloc(N * sizeof(listElement));
// element access
for (int i = 0; i < N; i++) {
listElement *le = ms->ptrToElements[i];
le->data = ...
le->next = NULL; // not clear what this pointer is used for...
}
// Memory deallocation
free(ms->ptrToElements);
free(ms);
It seems to me like struct new_element *element = malloc(sizeof(*element)) creates a structure of type element, whereas I thought it would only create a pointer to it. The following code proves to me I'm wrong:
struct new_element
{
int i;
struct new_element *next;
};
int main(void)
{
struct new_element *element = malloc(sizeof(*element));
element->i = 5;
element->next = NULL;
printf("i = %d, next = %p\n", element->i, element->next);
}
Output:
i = 5, next = (nil);
element->i was given the value 5 and element->next was given the value NULL. Doesn't that mean that element points to a structure, which would mean that there is a structure that was created? I thought that malloc would only give a pointer the size needed in memory.
The variable element is a pointer. When you define it, that sets aside space for the pointer.
If you just did this:
struct new_element *element;
You've created a pointer. It just doesn't point anywhere.
When you then call malloc(sizeof(*element)), that sets aside space big enough for what element points to, i.e. an instance of struct new_element. You then point the variable element to this section of memory.
This syntax:
element->i = 5;
Is the same as:
(*element).i = 5;
It dereferences the pointer element, giving you a struct new_element, then you access the member i.
If you did this, as you suggested in the comments:
struct new_element *element = malloc(sizeof(element));
You're not allocating the proper amount of space. You're setting aside enough space for a struct new_element * instead of a struct new_element. If the struct is larger than a pointer to it (likely in this case, since it contains a pointer to its own type), then you end of writing past the end of the allocated memory when modifying one of the members. This invokes undefined behavior.
typedef struct{
char id[15];
int count;
}hashtag;
typedef struct node{
hashtag *hashtag;
struct node*next;
}*link;
I'm writing a program to read hashtags from a sentence, and I want to store them in a list. I've already defined this two structures, and I can read and pass the hashtags to the function below but I need help allocating memory in order to copy the string to the list.
void check_insert(char newh[]){
link x;
//malloc to allocate memory for the string I want to copy
strcpy(x->hashtag->id, newh);
x->hashtag->count += 1;
head = insert_end(head, x->hashtag); //head is a global variable that points to the 1st element of the list
}
You should allocate and initialize the pointer x in check_insert, it is undefined behavior to dereference it and access its members without allocation first:
void check_insert(char newh[]){
link x = malloc(sizeof *x);
x->hashtag = malloc(sizeof *x->hashtag);
// strcpy(x->hashtag->id, newh); <-- UB if newh is larger than 14 in size
x->hashtag->id[0] = '\0';
strncat(x->hashtag->id, newh, sizeof(x->hashtag->id));
x->hashtag->count = 1;
head = insert_end(head, x->hashtag);
}
So I am working on a project in C where we need to implement malloc and free (meaning, we CANNOT use any C memory management functions such as malloc() or free()). This is only a code snippet, but it includes all relevant parts.
struct block_header
{
int size;
};
typedef struct FList_elem
{
struct block_header * header;
struct list_elem elem;
} FLelem;
void * manual_malloc(size_t size)
{
freeBlock = (FLelem *) mem_sbrk(newsize);
freeBlock->header = (struct block_header *) freeBlock;
freeBlock->header->size = newsize;
}
When allocating a new "block" of memory, we represent it via a structure FList_elem. In order to "allocate memory" for the struct, we point it at a memory address returned by mem_sbrk (works just like sbrk()). My question is, how do we establish memory for variables like size? Initially it's address is 0x0, and so assignments or references to it cause seg faults. Does it need to be a pointer so that we can set it's address, and then the value?
Instead of your original code, which stores a pointer to block_header inside the FList_elem structure, you can just embed the whole block_header structure inside the FList_elem structure:
struct block_header
{
int size;
};
typedef struct FList_elem
{
/* OLD code: struct block_header * header; */
/* Better code: block_header is embedded inside FList_elem structure */
struct block_header header;
struct list_elem elem;
} FLelem;
In this way, you don't need to allocate block_header separately: it's just there with the rest of FList_elem bytes.
And to set the size field (and any other attribute you may add to your block header) you can just do:
freeBlock->header.size = newsize;
When allocating the requested size, you need to add the header elements - and the pointer to the next block (eventually - the size can be computed with pointer difference as a space optimization... if this is embedded staff they are 4 bytes per block saved).
Since I think there are some incongruences, I have reported here my interpretation (not tested) of what you are trying to do:
struct block_header
{
int size;
};
typedef struct FList_elem
{
struct block_header header; // removed a * here: size is in place
struct Flist_elem *elem; // added a * here: that's the pointer to the next block.
} FLelem;
FLelem *memory_list = 0; // added a pointer for the global list - right?
void * manual_malloc(size_t newsize) // renamed as newsize here
{
freeBlock = (FLelem *) mem_sbrk(newsize + sizeof(FLelem));
freeBlock->header.size = newsize;
freeBlock->header.elem = memory_list;
memory_list = freeBlock;
// inserted freeBlock at the head of memory_list;
return (void*)(freeBlock+1); // +1 to skip the header as a return address
}
The caller of the function will have returned the space after the header.
Your manual_free() function will take as an argument this returned memory pointer, and it will need to subtract and go back a freeblock in memory in order to find the header and to release the block, and than you will need some sort of tree (bit tree) to keep of track of the holes left free... If you need to handle dynamic memory - and that's where it start being interesting.
Hope I have not done errors and that it's clear enough!
#include <stdlib.h>
struct st *x = malloc(sizeof *x);
Note that:
x must be a pointer
no cast is required
include appropriate header
I'm having some issues with my linked list. I have struct dListNode used as the nodes for the list with a pointer to struct data, which is used as the data storage.
struct data{
int payload;
};
struct dListNode{
struct dListNode *next;
struct dListNode *prev;
struct data *val;
}*dHead, *dTail;
My program compiles fine, but I get a segmentation fault at the line indicated below. What is going on?
newDNode = (struct dListNode *)malloc(sizeof(struct dListNode)+sizeof(struct data));
printf("newnode created\n"); // this prints
newDNode->val->payload = rand() % 1000; //error here?
printf("newnode payload: %i\n", newDNode->val->payload); //seg fault before this is printed
Also, I have already ran this line in the program: srand((unsigned)time(NULL))
NewDNode doesn't have an associated memory allocation to it. So when you do
newDNode = (struct dListNode *)malloc(sizeof(struct dListNode)+sizeof(struct data));
This just allocates memory to newDnode and not to newDnode->val. Since newDNode->val just contains whatever was leftover in the memory at that location (or maybe even 0 (NULL pointer)), and you try to assign a value to the memory location which is neither on the stack nor on the heap, the program complains because you are trying to access unassigned part of memory.
Here's what you should do:
newDNode = malloc(sizeof(struct dListNode));
newDnode->val = malloc(sizeof(struct data));
printf("newnode created\n");
newDNode->val->payload = rand() % 1000;
printf("newnode payload: %i\n", newDNode->val->payload);
And as a tip, always try to not cast the result returned by malloc (or any other memory allocation function). Its considered bad practice.
You problem is that you never initialized the pointer val:
newDNode->val->payload = rand() % 1000;
newDNode is allocated, but none of the fields are initialized, so dereferencing val will likely cause that segmentation fault.
So you will need to allocate something for val before you access it.
newDNode = malloc(sizeof(struct dListNode)); // Allocate "dListNode"
newDNode->val = malloc(sizeof(struct data)); // Allocate "data"
newDNode->val->payload = rand() % 1000;
You have a slight misunderstanding of how the allocation works. You need to allocate each pointer separately.
EDIT : And alternate approach is just to not use a pointer for val in the first place:
// Declare struct as:
struct dListNode{
struct dListNode *next;
struct dListNode *prev;
struct data val;
}*dHead, *dTail;
// Build object like this:
newDNode = malloc(sizeof(struct dListNode));
newDNode->val.payload = rand() % 1000;
val does not point to a valid data structure. Sure, you malloc enough size, but that doesn't mean that val is now all of a sudden a valid pointer. You should initialize newDNode with just the size of a dListNode and then separately initialize newDNode->val to point to some valid chunk of memory large enough for a data structure.
On a side note, you don't need to cast the return value of malloc. That's a C++ thing; in C a void* can be implicitly converted to any other pointer type.
Second, if you typedef your struct types you don't have to write struct all over the place when using them.
You're never setting newDNode->val to point to anything. So when you try to set newDNode->val->payload, you're dereferencing either a null pointer or some random address (i forget which). Neither case is what you want.
I don't really like the idea of malloc'ing both the structs in the same statement. But if you insist on doing it, you'll need to do something like
newDNode->val = (struct data*)((char*) newDNode + sizeof(struct dListNode));
A better way, though, is to change the struct so that val is a struct rather than just a pointer to one. Then sizeof(struct dListNode) includes the size of struct data, and you can access it like newDListNode->val.payload without having to malloc the data part separately or do any tricky pointer math. (Drawback being, you'd have to copy the structs to store them in an array, swap them around, etc.)