struct Temp {};
struct Temp *newTemp() {
struct Temp *temp = malloc(sizeof(struct Temp));
return temp;
}
int main() {
struct Temp *temp = newTemp(); // any problem?
return 0;
}
Is there any problem with returning an instance of a struct from inside the function (factory method).
Will the pointer will be invalid. I was suggested that if you return a pointer it should point to something on the caller's stack, a global, or something on the heap
C structure must contain at least one member as per standard, but gcc allows it as an extension.
And what you did is legal - you can return pointer to dynamically allocated memory and use it in other function.
Memory allocated by malloc has storage duration (allocated storage duration) beyond the scope on which it is declared. You can use it without any problem.
It's expected that you would free the allocated memory and check the return value of malloc (saves you from dereferencing null in case of failure).
Standard N1570 C11 standard also mentions it under §7.22.3 memory management functions:
....The lifetime of an allocated object extends from the allocation until the deallocation.
You have two ways to return a struct from a function:
return a pointer to a dynamically allocated struct (your example code)
The lifetime of a dynamically allocated object extends until it is de-allocated, so the caller will be able to use it. Simply you must not forget to free it when you no longer need it. Not doing so is called a memory leak. So a fixed version should be:
struct Temp {
int i; // a struct should not be empty...
};
struct Temp *newTemp() {
struct Temp *temp = malloc(sizeof(struct Temp));
return temp;
}
int main() {
struct Temp *temp = newTemp(); // any problem?
// use temp...
free(temp);
return 0;
}
return a temporary object
A struct is a first class object in C, so you can directly assign to it. You can then build a struct in a function and return it (beware: returning a pointer to it would actually return a dangling pointer because lifetime would end when function returns). So an alternate way is:
struct Temp {
int i; // a struct should not be empty...
};
struct Temp newTemp() {
struct Temp temp;
// set values of temp members...
return temp;
}
int main() {
struct Temp temp = newTemp(); // no problem?
// use temp...
return 0;
}
The good news here is that the struct is an automatic object in the caller, so it has not to (and shall not) be free-d. And decent compilers can even elide the copy by having the callee to directly use the caller automatic storage.
malloc allocates memory on heap. Objects allocated on heap has static storage duration. It is valid to return a pointer from a function to an object allocated by malloc.
Note that the empty struct you are using is not standard C. GCC provide this feature as an extension.
Related
Consider you have a function and the function output will be the Head and Tail address of a Linked List (a function for copy a Linked List in another address):
struct path *copyPath(struct path *head) {
struct path *temp = malloc(sizeof (struct path));
// array of newHead and newTail
struct path *resultPath[2];
struct path *newHead = NULL;
struct path *newTail = NULL;
while (head != NULL) {
temp = malloc(sizeof (struct path));
if (newHead == NULL) {
// Add a new node to the first of list and save newHead as the beginning of the list
} else {
// Add the other nodes and save the last node address as newTail
}
head = head -> next;
}
resultPath[0] = newHead;
resultPath[1] = newTail;
return resultPath;
}
I defined an array of struct path and I return it. In the main function an array has been defined:
struct path *newPath;
newPath = copyPath(path_head, nextNode);
When I run it, I do not have anything in newPath and it is empty.
So, what is the best way to return these addresses and why I do not have it in newPath?
Also, when I use:
struct path *newPath[2];
newPath = copyPath(path_head, nextNode);
I have an error: error: assignment to expression with array type
How to can I pass these two values to the main function?
In addition to the comments, your funciton has two primary problems, 1) you leak memory by overwriting the address of the first allocated block of memory; and 2) you attempt to return returnPath which has automatic storage duration declared local to copyPath.
Memory Leak
You leak memory in your function by overwriting the pointer temp before it has been assigned, e.g.
struct path *temp = malloc(sizeof (struct path));
...
while (head != NULL) {
temp = malloc(sizeof (struct path));
By allocating a second time for temp before you have assigned the original pointer to another variable, you lose the original pointer in temp pointing to the first block of memory allocated. That memory can never be freed by your program from that point forward.
Returning Array with Automatic Storage Declared Local to Function
When I run it, I do not have anything in newPath and it is empty.
struct path *resultPath[2]; declares an array-of-pointers to struct path (two of them). Automatic storage for resultPath is declared local to copyPath within it function stack frame. When copyPath returns, all local variables with automatic storage duration are destroyed (function stack frame memory is released for reuse). This is expressly explained by C11 Standard - §6.2.4 Storage durations of objects
1) An object has a storage duration that determines its lifetime. There are four storage durations: static, thread, automatic, and allocated. Allocated storage is described in 7.22.3.
2) The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it. An object exists, has a constant address,33) and retains its last-stored value throughout its lifetime.34) If an object is referred to outside of its lifetime, the behavior is undefined. The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.
6) For such an object that does not have a variable length array type, its lifetime extends from entry into the block with which it is associated until execution of that block ends in any way.
(emphasis ours)
So, what is the best way to return these addresses and why I do not have it in newPath?
In order to return resultPath, you need to allocate storage for it dynamically and return a pointer to it. Objects with allocated storage duration extend for the lifetime of the program or until they are freed.
The easiest way to declare and allocate for an object capable of storing two pointers to struct path is to declare an pointer-to-pointer to struct path, (effectively a dynamic array of pointers), and allocate storage for two pointers, e.g.
/* allocate & validate 2 pointers to struct path */
struct path **resultPath = malloc (sizeof *resultPath * 2);
if (!resultPath) { /* always validate all memory allocations */
perror ("malloc resultPath failed.");
return NULL;
}
...
resultPath[0] = newHead; /* newHead & newTail must point to allocated memory */
resultPath[1] = newTail;
return resultPath;
You can now safely return resultPath and storage for resultPath will survive the return eliminating your access of memory that is no longer available. You then access newHead and newTail through newPath[0] and newPath[1], respectively, in the caller.
You will also need to change the return type for copyPath to stuct path **, e.g.
struct path **copyPath(struct path *head)
and update the type in the caller.
Whenever you allocate a dynamic memory(using malloc, calloc, realloc), appropriately typecast the return address to the proper data type. Because these functions return void pointer. In the below line you are assigning the void pointer type address to the struct path type pointer.
temp = malloc(sizeof (struct path));
It can be written as:
temp = (struct path *)malloc(sizeof (struct path));
Second thing, you are returning a array of pointer of type "struct path", but you are collecting this return array of pointer value in a regular pointer of type "struct path" in main which is against the C standard. Correct this mistakes and try to run the code.
In Main use array of pointer to collect the return value:
struct path *newPath[2];
newPath = copyPath(path_head, nextNode)
I have two structs
struct obj_t {
int id;
float x;
float y;
};
struct cluster_t {
int size;
int capacity;
struct obj_t *obj;
};
As you can see, there is pointer to first obj_t inside cluster_t
What I want to do is to free every obj_t from array inside cluster_t
Do I have to write it with for loop like this?
void clear_cluster(struct cluster_t *c)
{
for(int i = 0; i<c->size;i++)
{
free(&c->obj[i]);
}
free(c->obj);
}
Or is it ok to free the memory just like this ?
void clear_cluster(struct cluster_t *c)
{
free(c->obj);
}
There should be one free() for every malloc() you have, and executed in the opposite order from which it was allocated.
The field obj of cluster_t is a pointer to an array of object_t. This is probably allocated with one malloc() when initializing your cluster_t (something like c->obj = malloc(c->capacity*sizeof(*c->obj))), so it only needs to be freed with one call to free(). You would then want to free the cluster_t allocation itself (assuming it too was dynamically allocated):
free(c->obj);
free(c);
There would be a difference, however, if each object_t itself had a dynamic allocation within it. (In your example, object_t does not.) In that case, you would have needed to iterate through the array and malloc() an allocation when you created the array, and therefore do the reverse and free() each at the end.
It depends on how you allocated. It seems you did something like
struct cluster_t cluster;
cluster.obj = malloc(sizeof (struct obj_t) * SOMENUMBER);
in this case, cluster.obj is just a pointer to an array. All you need to do is
free(cluster.obj)
or
free(c->obj)
in that function which receives a pointer to c.
You only have to iterate over the array calling free if you have an array of pointers.
Remember that & takes the memory address of the variable. You don't free the pointer, you free the memory that the pointer points to. You will never do something like free(&pointer).
I have a struct which contains 2 integers and a pointer to another struct. I allocate memory for struct first and then for the pointer. When I free the memory I free up the pointer first and then I free up the struct.
When I run my program and call the function that frees memory it crashes when the call is made. When I don't call the function that frees memory it works fine, but then I'm not freeing up the memory.
I tried removing the line that frees the memory allocated to the pointer and the program doesn't crash, but I don't think thats right since a "free" is needed for every "malloc/calloc" right? Anyone see anything wrong with the freeing function?
//Define a struct data type
struct q_element
{
//Declaration of struct members
int element;
int priority;
struct q_element *next_element;
};
//Method to allocate memory
struct q_element* allocateStruct()
{
//Declaration of a variable
struct q_element *e;
//Allocate memory for one queue element
e = malloc(sizeof(struct q_element));
//Allocate memory for one pointer to a queue element
e->next_element = calloc(1,sizeof(struct q_element*));
//Initialize integer members of queue element
e->element = 0;
e->priority = 0;
return e;
}
//Method to free memory allocated
void freeStruct(struct q_element* e)
{
//Free up pointer member
free(e->next_element);
//Free up struct
free(e);
}
You don't need to allocate memory for the next_element pointer. The pointer is already there, just like int element for example.
So if you want to allocate just one element, you can set the next_element pointer to NULL and everything is fine.
You are not allocating enough memory for e->next_element in the line:
e->next_element = calloc(1,sizeof(struct q_element*));
// ^^^ remove the *
That should be:
e->next_element = calloc(1,sizeof(struct q_element));
If you used e->next_element as though it were a valid pointer, you most likely ended up accessing memory that you did not allocate. That clobbered some of the bookkeeping information created by calloc, which lead to problems when you called free.
In
//Allocate memory for one pointer to a queue element
e->next_element = calloc(1,sizeof(struct q_element*));
you allocate space for a pointer to a q_element structure, rather than a q_element structure. Do you attempt to write to this structure, because if so, that's probably where it goes wrong.
As a side note you might be better off just doing
e->next_element = 0
inside allocate_struct and then doing e->next_element = allocate_struct() outside the function later.
In addition to what everyone else is mentioning about allocation, you also need a sentinel to check if the next_element was already freed. You may be attempting a double free.
Try the following code:
void freeStruct(struct q_element* e)
{
//Free up pointer member
if(e->next_element != 0){
free(e->next_element);
e->next_element = 0;
}
//Free up struct
free(e);
}
In legacy C code I have one pointer basically an array of size equal to one of enumerator and it is static in local scope. But now I have to remove that enumeration and now this static local array is giving error. I can convert that array to normal pointer and then allocate it dynamically but I am not sure how to do that. Below is sample code I have simplified from existing code base.
enum
{
E1,
E2,
EOL
};
void func
{
//static int array[EOL]; //-> that how it was earlier
static int *array = (int*)malloc(sizeof(int)*EOL); //Will this allocated memory only once
//or on every invokation.
free(array);//will it free the memory more than once?
}
Now I can move array pointer to global scope and then allocate it in main and free it in atexit functions but I want to keep changes minimum as I am not sure of impact it will have in shared projects?
Thanks
The malloc will occure only once.
1) You can use a static boolean to let you know if the pointer in the array variable can be free.
2) You can free the pointer then set it to NULL. The next occuration of the free will do nothing.
If you want to keep changes minimal then simply move the enumeration definition inside the function body before this static variable. Or you can use even an unnamed enum with one enumerator for the size of the array.
I do not understand your attempts to substitute the array for a dynamically allocated array.
Moreover at present C allows to use variable length arrays. So your could define the function such a way that it had a parameter that would specify the size of the local (non-static) array.
You can't initialise a static variable with something non const if you are using C.
If you are using C++, then the static pointer will only get a memory pointer allocated to it once.
I just solved the problem by using one function which basically is collects all memory allocated to local static pointers like above and then other functions free them during the end as it is registered using atexit function.
struct node
{
node *next;
void *content;
};
node* head = NULL, tail =NULL;
void addToList(void* ptr)
{
struct node* p = (struct node*)malloc(sizeof(struct node));
p->next = NULL;
p->conent = ptr;
tail->next = p;
tail = p;
return;
}
void freeList()
{
struct node* p = NULL, p1 = NULL;
for(p = head; p != NULL; p = p->next)
{
free(p1);
free(p->content);
p1 = p;
}
head = tail = NULL;
return;
}
/*
*/
void func
{
//static int array[EOL]; //-> that how it was earlier
static int *array = (int*)malloc(sizeof(int)*EOL); //Will this allocated memory only once
addToList(array); //or on every invokation.
free(array);//will it free the memory more than once?
}
As you can see it above code a linked list is created in separate .c file and using .map method head,tail and node will not be exposed to outside world only addToList and freeList will be visible. In every places just after doing a malloc I am calling addToList and then freeList will free up the memory.
Thanks
Am unable to run this code...
#include<cstdio>
int main()
{
struct a{
int b;
struct a *next;
};
typedef struct a no;
no *n;
n->b = 12;
n->next = NULL;
n->next->b = 12;
n->next->next = NULL;
printf("%d %d", n->b, n->next->b);
getchar();
return 0;
}
When you say:
no *n;
you get an uninitialised pointer. When you use that pointer, you get undefined behaviour.
You allocated space for a pointer to a structure, but you didn't allocate space for the actual structure. This means that you don't have a memory address for the structure you are using.
In addition, the pointer points to some random memory address because you didn't initialize it. As a result, you could be trying to read and write to memory that doesn't belong to you, which can cause your program or even your system to crash because of the undefined behavior that results.
As #Neil Butterworth said, you get an uninitialised pointer. This mean that this pointer could point to anywhere, thus giving an access violation error. The way to fix this is simple, just call malloc() before using that pointer. malloc() gives that pointer a valid and usable address, so no one will complain about that.
You're declaring a struct INSIDE a function.
Declare the struct OUTSIDE of the function.
The typedef should be declared outside the function too.
#include<cstdio>
struct a{
int b;
struct a *next;
};
typedef struct a no;
int main()
{
///... your code...
}
try something like this:
no *n = (no*)malloc(sizeof(no));
#include <cstdio>
/* declaring the struct in the function definition may be possible (I'm not sure,
actually, haha). Unless you have a GOOD reason, it's good practice to declare
structs, globals, typedefs, etc... outside the function */
typedef struct a{
int b;
struct a *next;
} no;
int main()
{
no *n;
/* Here, you have a pointer. Remember these are simply (generally) 32-bit values
defined in your stack space used to store a memory location which points to your
ACTUAL struct a! Depending on what USED to be in the stack space, this could
point ANYWHERE in memory, but usually you will find that it points to the NULL
memory location, which is just address "0". To get this to point to something,
you have to allocate empty space on your heap to store your struct... */
n = malloc(sizeof(no));
/* Now your pointer n points to an allocated 'struct a', and you can use it like
normal */
n->b = 12;
n->next = NULL;
/* You just set n->next, which is another 'no' pointer, to NULL. This means that
n->next points nowhere. So, just like above you have to malloc another instance
of the struct! */
n->next = malloc(sizeof(no));
/* NOW you can use n->next with no ill effects! */
n->next->b = 12;
n->next->next = NULL;
printf("%d %d", n->b, n->next->b);
getchar();
/* After you're done with your structs, you want to free them using the POINTERS
that reference them */
free(n->next);
free(n);
return 0;
}