I have a structure that looks like this:
typedef struct{
char* name;
int count;
Node **subnodes;
}Node;
I receive name and count over network one by one for the whole k-ary tree and then I reconstruct the tree. How do I malloc this struct?
Node *n = NULL;
fun(n, buf); //call function fun
void fun(Node *n, void *buf){
//successfully extracted name and count from buf
// say count is 5, i.e. this node should have 5 subnodes and
// name is root
n = malloc(sizeof(*n)+strlen(name));
n->name = name;
n->count = count;
for(int i=0; i<n->count;i++)
fun(n->subnodes[i], buf+some_increment);
}
This crashes as soon as I call fun for the second time. How should I malloc properly? Should I be malloc-ing each subnode?
First off, you realise this is leaky? n is just on the stack - you aren't returning it or "saving" the value you give it anywhere permanently.
Then you haven't actually allocated any memory for subnodes, so by indexing into it you are reading unallocated memory.
Without a more complete example it is hard to further, but at a minimum you need to malloc something for subnodes.
Yes, you will have to malloc each node. I see a couple of issues here:
You are neglecting in malloc(sizeof(*n)+strlen(name)) to provide space for the null terminator. This statement should read malloc(sizeof(*n)+strlen(name)+1). Also you should set the name pointer in the struct to the end of the struct and then strcpy the buffered name to it
n -> name = (char *)(n + 1)
strcpy(n -> name, buffered_name)
I presume the buffered version is transient.
You are allocating no space for the variable sized array of child nodes. This has to be done as a separate malloc or you have to embed it in the Node malloc (I'd recommend placing it between the Node header and the name string content.
Note, I am making a few liberal assumptions about what the code really looks like since this is clearly an incomplete snippit with typos. e.g. subnodes <-> subnode
Addendum: Code snippet (untested so normal caveats apply):
typedef struct
{
char* name;
int count;
Node **subnodes;
}
Node;
Node *fun(void *buf)
{
...
//successfully extracted name and count from buf
// say count is 5, i.e. this node should have 5 subnodes and
// name is root
// Allocate space for the node and its data.
Node *node_ptr = malloc(sizeof(Node) + count * sizeof(Node *) + strlen(name) + 1);
// Set the name pointer and copy the name from the I/O buffer.
node_ptr -> name = (char *)(node_ptr + 1) + count * sizeof(Node *); // set the name pointer to the right location.
strcpy(node_ptr -> name, name); // copy the buffered value to the node value.
// Establish the count from the I/O buffer.
node_ptr -> count = count;
// Set the subnodes address.
node_ptr -> subnodes = (char *)(node_ptr + 1);
// Get the child nodes.
for(int child = 0; child < node_ptr -> count; child++)
node_ptr -> subnodes[child] = fun(buf + some_increment);
}
I have a structure that looks like this:
typdef struct{
char* name;
int count;
Node **subnodes;
}Node;
Not really, because it is typedef not typdef.
As John3136 pointed out, your function allocates memory in n which is a local variable. Plus you are assigning count and name which do not appear to be passed to fun.
It also looks to me like the function fun will recurse indefinitely.
You call fun which (in the last line) calls fun which therefore calls fun again, and so on until you run out of stack.
(Edited to add)
Trying to guess what is wanted, I have got this working example going:
#include <memory.h>
#include <stdlib.h>
#include <stdio.h>
typedef struct Node {
char* name;
int count;
Node **subnodes;
}Node;
void makeNode(Node * &n, const char * name, const int count)
{
// make the node itself
n = (Node *) malloc(sizeof(*n));
// allocate room for the name
n->name = (char *) malloc (strlen (name) + 1);
// copy in the name
strcpy (n->name, name);
// save the count of subnodes
n->count = count;
// allocate memory for subnode pointers (not the subnodes themselves)
if (count > 0)
n->subnodes = (Node **) malloc (sizeof (Node *) * count);
else
n->subnodes = NULL;
} // end of makeNode
int main ()
{
Node *node = NULL;
makeNode(node, "foo", 3);
makeNode(node->subnodes [0], "the", 0);
makeNode(node->subnodes [1], "slithy", 0);
makeNode(node->subnodes [2], "toves", 0);
for (int i = 0; i < 3; i++)
printf ("Node %i, name = %s\n", i, node->subnodes [i]->name);
printf ("Done!\n");
} // end of main
This runs OK:
Node 0, name = the
Node 1, name = slithy
Node 2, name = toves
Done!
Note, I compiled with g++, not gcc. However it should give you some ideas to go on with.
(You don't have references in C, so you really need C++ for this to work)
Related
I have a block of pointers to some structs which I want to handle (i.e. free) separately. As an example below there is an integer double-pointer which should keep other pointers to integer. I then would like to free the second of those integer pointers (in my program based on some filterings and calculations). If I do so however, I should keep track of int-pointers already set free so that when I iterate over the pointers in the double-pointer I do not take the risk of working with them further. Is there a better approach for solving this problem (in ANSI-C) without using other libs (e.g. glib or alike)?
Here is a small simulation of the problem:
#include <stdio.h>
#include <stdlib.h>
int main() {
int **ipp=NULL;
for (int i = 0; i < 3; i++) {
int *ip = malloc(sizeof (int));
printf("%p -> ip %d\n", ip, i);
*ip = i * 10;
if ((ipp = realloc(ipp, sizeof (int *) * (i + 1)))) {
ipp[i] = ip;
}
}
printf("%p -> ipp\n", ipp);
for (int i = 0; i < 3; i++) {
printf("%d. %p %p %d\n", i, ipp + i, *(ipp+i), **(ipp + i));
}
// free the middle integer pointer
free(*(ipp+1));
printf("====\n");
for (int i = 0; i < 3; i++) {
printf("%d. %p %p %d\n", i, ipp + i, *(ipp+i), **(ipp + i));
}
return 0;
}
which prints something like
0x555bcc07f2a0 -> ip 0
0x555bcc07f6f0 -> ip 1
0x555bcc07f710 -> ip 2
0x555bcc07f6d0 -> ipp
0. 0x555bcc07f6d0 0x555bcc07f2a0 0
1. 0x555bcc07f6d8 0x555bcc07f6f0 10
2. 0x555bcc07f6e0 0x555bcc07f710 20
====
0. 0x555bcc07f6d0 0x555bcc07f2a0 0
1. 0x555bcc07f6d8 0x555bcc07f6f0 0
2. 0x555bcc07f6e0 0x555bcc07f710 20
Here I have freed the middle int-pointer. In my actual program I create a new block for an integer double-pointer, iterate over the current one, create new integer pointers and copy the old values into it, realloc the double-pointer block and append the new pointer to it, and at the end free the old block and all it's containing pointers. This is a bit ugly, and resource-consuming if there is a huge amount of data, since I have to iterate over and create and copy all the data twice. Any help is appreciated.
Re:
"This is a bit ugly, and resource-consuming if there is a huge amount of data, since I have to iterate over and create and copy all the data
twice. Any help is appreciated."
First observation: It is not necessary to use realloc() when allocating new memory on a pointer that has already been freed. realloc() is useful when needing to preserve the contents in a particular area of memory, while expanding its size. If that is not a need (which is not in this case) malloc() or calloc() are sufficient. #Marco's suggestion is correct.
Second observation: the following code snippet:
if ((ipp = realloc(ipp, sizeof (int *) * (i + 1)))) {
ipp[i] = ip;
}
is a potential memory leak. If the call to realloc()_ fails, the pointer ipp will be set to null, making the memory location that was previously allocated becomes orphaned, with no way to free it.
Third observation: Your approach is described as needing:
Array of struct
dynamic memory allocation of a 2D array
need to delete elements of 2D array, and ensure they are not referenced once deleted
need to repurpose deleted elements of 2D array
Your initial reaction in comments to considering using an alternative approach notwithstanding, Linked lists are a perfect fit to address the needs stated in your post.
The fundamental element of a Linked List uses a struct
Nodes (elements) of a List are dynamically allocated when created.
Nodes of a List are not accessible to be used once deleted. (No need to track)
Once the need exists, a new node is easily created.
Example struct follows. I like to use a data struct to contain the payload, then use an additional struct as the conveyance, to carry the data when building a Linked List:
typedef struct {//to simulate your struct
int dNum;
char unique_name[30];
double fNum;
} data_s;
typedef struct Node {//conveyance of payload, forward and backward searchable
data_s data;
struct Node *next; // Pointer to next node in DLL
struct Node *prev; // Pointer to previous node in DLL
} list_t;
Creating a list is done by creating a series of nodes as needed during run-time. Typically as records of a database, or lines of a file are read, and the elements of the table record (of element of the line in a file) are read into and instance of the data part of the list_s struct. A function is typically defined to do this, for example
void insert_node(list_s **head, data_s *new)
{
list_s *temp = malloc(sizeof(*temp));
//insert lines to populate
temp.data.dNum = new.dNum;
strcpy(temp.data.unique_name, new.unique_name);
temp.fNum = new.fNum
//arrange list to accomdate new node in new list
temp->next = temp->prev = NULL;
if (!(*head))
(*head) = temp;
else//...or existing list
{
temp->next = *head;
(*head)->prev = temp;
(*head) = temp;
}
}
Deleting a node can be done in multiple ways. It the following example method a unique value of a node member is used, in this case unique_name
void delete_node_by_name(list_s** head_ref, const char *name)
{
BOOL not_found = TRUE;
// if list is empty
if ((*head_ref) == NULL)
return;
list_s *current = *head_ref;
list_s *next = NULL;
// traverse the list up to the end
while (current != NULL && not_found)
{
// if 'name' in node...
if (strcmp(current->data.unique_name, name) == 0)
{
//set loop to exit
not_found = FALSE;
//save current's next node in the pointer 'next' /
next = current->next;
// delete the node pointed to by 'current'
delete_node(head_ref, current);
// reset the pointers
current = next;
}
// increment to next node
else
{
current = current->next;
}
}
}
Where delete_node() is defined as:
void delete_node(list_t **head_ref, list_t *del)
{
// base case
if (*head_ref == NULL || del == NULL)
return;
// If node to be deleted is head node
if (*head_ref == del)
*head_ref = del->next;
// Change next only if node to be deleted is NOT the last node
if (del->next != NULL)
del->next->prev = del->prev;
// Change prev only if node to be deleted is NOT the first node
if (del->prev != NULL)
del->prev->next = del->next;
// Finally, free the memory occupied by del
free(del);
}
This link is an introduction to Linked Lists, and has additional links to other related topic to expand the types of lists that are available.
You could use standard function memmove and then call realloc. For example
Let's assume that currently there are n pointers. Then you can write
free( *(ipp + i ) );
memmove( ipp + i, ipp + i + 1, ( n - i - 1 ) * sizeof( *pp ) );
*( ipp + n - 1 ) = NULL; // if the call of realloc will not be successfull
// then the pointer will be equal to NULL
int **tmp = realloc( ipp, ( n - 1 ) * sizeof( *tmp ) );
if ( tmp != NULL )
{
ipp = tmp;
--n;
}
else
{
// some other actions
}
I'm making a program where I save input strings from fgets in a list, they have a fixed maximum lenght but can also be shorter; i save them like this:
typedef char line[LINE_SIZE];
struct node{
line *t; //pointer and not just a variable so I can "detach" the allocation to do stuff
struct node *prev;
struct node *next;
};
but, in my program I just do malloc(sizeof(line)) which is an array with the maximum fixed lenght.
My question is, if I were to allocate something like malloc( strlen( str ) + sizeof( ( char )'\0' ) ) to precisely use only the memory needed, how can I point it?
Is it okay using a char* inside the node struct? Do I risk something?
I have heard about flexible arrays inside the structs but I don't want to put the array directly inside the struct, because for the program I need to be able to detach it and then point to it with another pointer
malloc() returns the address it allocated, you can assign the return value to a variable and point it. You don't need to always allocate maximum or the same size of memory even though the variable is the same member of a struct.
char* line=malloc(strlen(str)+1); // +1 for null terminate
strcpy(line, "This is a str"); // points the memory of returned
Using a char* in a struct is absolutely fine. Please treat a member of struct like a plain variable.
struct node
{
char* t;
struct node* prev;
struct node* next;
}
node n;
n.t = malloc(strlen(str) + 1); // it's fine.
strcpy(n.t, "This is a node"); // using the memory you allocated above
n.prev = n.next = NULL;
... // doing some processing
free(n.t); // don't forget to call free() when you're done using the memory.
For your purpose, you must allocate the node structure and the line fragment separately.
Depending on what the rest of the code assumes, you could allocate just the space for the string for each line instead of a full array, but you must change the node structure to use a char *t; instead of a line typedef. Note that it is very confusing to typedef arrays.
The only caveat is you must be careful when modifying these strings as you cannot add any characters at the end, nor insert any characters by moving contents beyond their allocated length. As a rule of thumb, if you reallocate these strings whenever you modify them, you should be safe.
Here is a simple example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char *t; //pointer and not just a variable so I can "detach" the allocation to do stuff
struct node *prev;
struct node *next;
};
struct node *read_file(FILE *fp) {
char buf[128];
struct node *head = NULL, tail = NULL, *n = NULL;
while (fgets(buf, sizeof buf, fp)) {
buf[strcspn(buf, "\n")] = '\0'; // strip the trailing newline if present
n = malloc(sizeof(*n));
if (n == NULL)
abort();
n->prev = tail;
n->next = NULL;
n->t = strdup(buf);
if (n->t == NULL)
abort();
if (tail == NULL) {
head = n;
} else {
tail->next = n;
}
tail = n;
}
return head;
}
I don't understand why my program seg faults at this line: if ((**table->table).link == NULL){ I seem to have malloc-ed memory for it, and I tried looking at it with gdb. *table->table was accessible and not NULL, but **table->table was not accessible.
Definition of hash_t:
struct table_s {
struct node_s **table;
size_t bins;
size_t size;
};
typedef struct table_s *hash_t;
void set(hash_t table, char *key, int value){
unsigned int hashnum = hash(key)%table->bins;
printf("%d \n", hashnum);
unsigned int i;
for (i = 0; i<hashnum; i++){
(table->table)++;
}
if (*(table->table) == NULL){
struct node_s n = {key, value, NULL};
struct node_s *np = &n;
*(table->table) = malloc(sizeof(struct node_s));
*(table->table) = np;
}else{
while ( *(table->table) != NULL){
if ((**table->table).link == NULL){
struct node_s n = {key, value, NULL};
struct node_s *np = &n;
(**table->table).link = malloc(sizeof(struct node_s));
(**table->table).link = np;
break;
}else if (strcmp((**table->table).key, key) == 0){
break;
}
*table->table = (**(table->table)).link;
}
if (table->size/table->bins > 1){
rehash(table);
}
}
}
I'm calling set from here:
for (int i = 0; i < trials; i++) {
int sample = rand() % max_num;
sprintf(key, "%d", sample);
set(table, key, sample);
}
Your hashtable works like this: You have bins bins and each bin is a linked list of key / value pairs. All items in a bin share the same hash code modulo the number of bins.
You have probably created the table of bins when you created or initialised the hash table, something like this:
table->table = malloc(table->bins * sizeof(*table->table);
for (size_t i = 0; i < table->bins; i++) table->table[i] = NULL;
Now why does the member table have two stars?
The "inner" star means that the table stores pointers to nodes, not the nodes themselves.
The "outer" start is a handle to allocated memory. If your hash table were of a fixed size, for example always with 256 bins, you could define it as:
struct node_s *table[256];
If you passed this array around, it would become (or "decay into") a pointer to its first element, a struct node_s **, just as the array you got from malloc.
You access the contents of the lĀ“bins via the linked lists and the head of linked list i is table->table[i].
You code has other problems:
What did you want to achieve with (table->table)++? This will make the handle to the allocated memory point not to the first element but tho the next one. After doing that hashnum times, *table->table will now be at the right node, but you will have lost the original handle, which you must retain, because you must pass it to free later when you clean up your hash table. Don't lose the handle to allocated memory! Use another local pointer instead.
You create a local node n and then make a link in your linked list with a pointer to that node. But the node n will be gone after you leave the function and the link will be "stale": It will point to invalid memory. You must also create memory for the node with malloc.
A simple implementation of your has table might be:
void set(hash_t table, char *key, int value)
{
unsigned int hashnum = hash(key) % table->bins;
// create (uninitialised) new node
struct node_s *nnew = malloc(sizeof(*nnew));
// initialise new node, point it to old head
nnew->key = strdup(key);
nnew->value = value;
nnew->link = table->table[hashnum];
// make the new node the new head
table->table[hashnum] = nnew;
}
This makes the new node the head of the linked list. This is not ideal, because if you overwrite items, the new ones will be found (which is good), but the old ones will still be in the table (which isn't good). But that, as they say, is left as an exercise to the reader.
(The strdup function isn't standard, but widely available. It also creates new memory, which you must free later, but it ensures, that the string "lives" (is still valid) after you have ceated the hash table.)
Please not how few stars there are in the code. If there is one star too few, it is in hash_t, where you have typecasted away the pointer nature.
I'm trying to add Process-structs to a linked list. Their definitions are as follows.
typedef struct {
char name[2];
int duration;
int priority;
int arrival;
} Process;
typedef struct {
Process p;
struct LinklistNode* next;
} LinklistNode;
The function that I'm using to create the process looks like this.
Process makeProcess(char nameIn[2], int durationIn, int priorityIn, int arrivalIn){
Process p = (Process*) malloc(sizeof(Process)); //getting an error
p->name = nameIn;
p->duration = durationIn;
p->arrival = arrivalIn;
p->priority = priorityIn;
}
I'm not sure that I'm doing that part right, and I'm also not sure that I should be returning a process or have it void, as this process "should" go into the linked list.
My code for creating a linked list node is as follows:
LinklistNode* create_linklist_node(Process pIn) {
LinklistNode* node = (LinklistNode*) malloc(sizeof(LinklistNode));
node->p = pIn;
node->next = NULL;
return node;
}
For a bit more context I'll be calling these functions in main() where I've tokenized a string from a file I'm reading from. I'm wondering the best way to make the Process struct. Right now I have this:
while(!feof(fPointer)){
//the i counter is for the first line in the text file which I want to skip
while ((fgets(singleLine, 1500, fPointer) != NULL) && !(i == 0)){
char *token = strtok (singleLine, delimit);
while(token != NULL){
printf(" %s\n", token);
token = strtok(NULL, delimit);
}
}
i++;
}
Bit of a long question but any references or additional information is always appreciated. Let me know if you have additional questions or need more info on what I'm doing or why I'm doing something. Or if you can find an example of something similar, that would be greatly appreciated as I haven't had much luck with that so far.
Thanks
You seem to have some issues with pointers. In this line
Process p = (Process*)malloc(sizeof(Process)); //getting an error
what you should be doing is
Process *p = malloc(sizeof(Process));
because unlike a new in some other languages, the malloc will just return a void *, (which in pure C can be automatically converted to any other data object pointer type). That pointer stores the address of the memory allocated for your struct. Of course you will also have to return the pointer, thus changing the return type to Process*.
Continuing with your original design, you would also have to store the Process* in the list-node, and consequently pass it to your construction method (LinklistNode* create_linklist_node(Process *pIn)).
You would then have to free both the node and possibly the pointer to the contained struct, if it is no longer used anywhere else, when you destroy the node.
However, given the size of your Process struct, I would suggest something else:
Since you already have your list nodes like this:
typedef struct{
Process p;
struct LinklistNode* next;
}LinklistNode;
You would allocate the memory for the actual process struct inside the node in during the call to create_linklist_node. Then you can just pass in a Process struct that is on the stack and copy it into the struct in the list, which lives in the heap-memory allocated by the create-call. In that case you don't need to dynamically allocate the Process at all, and the pointer issues in the first part become irrelevant.
LinkListNode *create_linklist_node(Process proc)
{
LinklistNode *p = malloc(sizeof *p);
if (p == NULL)
{
perror("Failed to allocate new node: ");
exit(EXIT_FAILURE);
}
p->p = proc;
p->next = NULL;
return p;
}
You would then do something like this:
Process proc = {{'a', 'b'}, 0, 0, 0};
LinklistNode *p = create_linklist_node(proc);
However, it is more common to have a method that directly creates and inserts the node into the list, for example, given:
typedef struct {
LinklistNode *head;
} Linklist; //doing this is kinda optional, using a simple pointer would do too
you could insert at the head of the list by doing something like:
void insert (Linklist *list, Process ins)
{
LinklistNode *tmp = create_linklist_node(ins);
tmp->next = list->head;
list->head = tmp;
}
We're trying to set the address of a struct to an address we are given but when we print out the address of the struct it seems to not be the same value as the address we are given.
/*a struct to keep block information*/
struct header{
int space;
int free; /* 1 = free space and 0 = full*/
struct header *nextHead;
struct header *prevHead;
};
typedef struct header node;
int myinit(int *array, int size){
int newSize = size;
node * nullPointer;
nullPointer = NULL; //make intermediatry node pointer for some bullshit reason
* (array) = newSize; /*store the size of the malloc at the first address*/
printf("Address : %p\n", &array[0]);
array++;
printf("Address after: %p\n", &array[0]);
/*initial block*/
node *root = (node *)&array; /*store the root at the next address available*/
printf("size of struct %lu\n", sizeof(struct header));
printf("%p\n", root);
root->space = newSize;
root->free = 1;
root->nextHead = nullPointer;
root->prevHead = nullPointer;
}
In the line
node *root = (node *)&array;
You're taking the address of "array" local variable. IOW, you take the address of value that's on the stack, not what you are expecting. You have to modify the function's signature like this:
int mymain(int **myarray, int size);
and modify its definition accordingly. Then, you can write:
node *root = (node *)array;
node *root = (node *)&array;
Here you obtain address of a pointer and cast it to other pointer. You should not do this. Here you must allocate the memory for the node:
node * root = (node *) malloc(sizeof(node));
// or this allocates the memory and puts zeros to it
node * root = (node *) calloc(1, sizeof(node));
Also, you don't need any nodes which points to NULL, you can simply use NULL like this:
node->nextHeader = NULL;
Also, instead of using &array[0], use array in this piece of code.
You will become less confused with pointers if you keep to simple code and understand every line you write. When you have a lot of ampersands and special signs in one line you're probably doing something wrong, train your spider sense for those situations.