Hi I am making a Queue abstact data type and I ran into a problem which I will try to explain as clearly as possible.
Basically I have a two structs one for an element and one for a queue (so you can initialize multiple queues).
struct element
{
TYPE value;
struct element* next;
};
struct queue
{
struct element* head;
struct element* tail;
int element_counter;
};
And I have a function which initializes my queue struct.
int make_new_queue(struct queue* name)
{
name = malloc(sizeof(struct queue));
name->head = NULL;
name->tail = NULL;
name->element_counter = 0;
}
The problem I ran into is foolproofing this code. For example I initialised my first queue in my main function.
struct queue* first = make_new_queue(first);
But if somebody tries to do the same thing again somewhere in the middle of the code write:
first = make_new_queue(first);
it overrides it and makes the head and tail pointers NULL. The thing I can't figure out is how to make my make_new_queue function better and check if there is something in the queue that I provide it, but still let me initialise empty queues.
Sorry for my english. I hope you get the idea of what I want to do. Thanks.
Initialize it to NULL and pass a pointer to pointer:
void make_new_queue(struct queue **name)
{
if (*name != NULL) return; /* Yet initialized ? */
*name = malloc(sizeof(struct queue));
if (*name == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
*name->head = NULL;
*name->tail = NULL;
*name->element_counter = 0;
}
struct queue *first = NULL;
make_new_queue(&first);
You can simply check if you variable name is NULL.
If your variable is non-null, you can alloc and initialize your queue else just do what you want to do.
There is really no good way to enforce what you want without discipline from the user. In my opinion, the best approach is to stick to known patterns.
You can use Alter Mann's approach to pass a pointer to a pointer to update the struct. The drawback is that is that you have to separate variable declaration and initialisation. It also relies on the user to initialise the pointer to the struct to NULL. If you forget it, the queue pointer will not be initialised and you don't even know, because you can't check against NULL.
struct stuff *stuff = NULL;
stuff_initialise(&stuff);
You can use your original approach to pass in the struct and return the same struct when it was initialised or a new one. It has the same problems as the first approach plus the possibility that you forget to assign the return value. You can, however, combine allocation and initialisation:
struct stuff *stuff = stuff_new(NULL);
The simplest way is not to pass the old pointer and rely on the user not to change the pointer after allocation. After all, the functions of the standard library suffer from the same problem:
char *buf = malloc(BUFSIZE);
buf = malloc(2 * BUFSIZE); // Memory leak
buf++; // Allowed, but a bad idea
free(buf); // Ouch!
FILE *f = fopen("palomino.txt", "r");
f = stdin; // Switch horses midstream?
You should design your API so that you have matching pairs of functions that define the scope of your struct:
struct stuff *stuff = stuff_create(...);
// use stuff ...
stuff_destroy(stuff);
Good naming should make clear that stuff acts as a handle and should not be changed and that after closing or destroying the handle, it is invalid. You should see these calls as first and last statements in functions. (This method is similar to the malloc/free or fopen/fclose pairngs of the standard library.)
Finally, if you as the user of a handle want to avoid accidential changes, you can define the pointer (not what it points to) as const:
struct stuff *const handle = stuff_create("X");
handle = stuff_create("Y"); // Compiler error
But I rarely see this. C programmers usually just use an unadorned pointer and remember to keep their fingers off the hotplate.
Related
I'm trying to COPY a queue into another queue in order that if I destroy one, it doesn't destroy the other one.
I tried using memcpy this way:
memcpy(queue1, queue2, sizeof(queue2));
But I get the following error:
expected ‘void * restrict’ but argument is of type 'Queue'
Is it possible to copy one queue into another?
EDIT
This is the structure of the queue:
typedef char *Following;
typedef struct _NodeQ {
Following element;
struct _NodeQ * next;
} NodeQ;
typedef struct {
int error;
NodeQ * first;
NodeQ * last;
} Queue;
memcpy is definitely not the way, because that would only get you as far as performing a "shallow copy". If you consider that your object can store pointers to external data, a shallow copy of that object will point to the exact same external data instead of duplicating everything ("deep copy").
(image source)
The method to perform a deep copy is entirely dependant on the implementation. It seems like your queue is using a simple linked list implementation (see how each NodeQ struct contains a pointer to another NodeQ struct, which has a pointer to another one, and so on). That is very common in C. The difficult part is figuring out how to copy the "data" portion of each object inside the queue (in this case the Following type variable). I can't tell what kind of library or framework you are using which defines the Queue type, you should refer to some documentation to help you on the specifics. Who knows, maybe you'll find a supported by the library way of copying the way you want. Nevertheless, I will attempt to do what you want, with some assumptions.
Speculation from this point onward
This is only a guess, but it seems like Following could represent a string, since it is a char pointer. The code I've written below uses this assumption. Note though that it is untested and a bit rushed, I'm just trying to illustrate how performing a manual deep copy may looks like in your scenario.
Queue queue2;
NodeQ *e2, *e2prev = NULL, *e2first = NULL;
// Iterate through all elements of the first queue
for (NodeQ *e1 = queue1.first; e1; e1 = e1->next) {
// Allocate memory for the new element of queue 2
if (!(e2 = (NodeQ*)malloc(sizeof(NodeQ)))) {
printf("not enough memory\n");
}
// Remember the first element of queue for future use
if (!e2first)
e2first = e2;
// Note that strlen here could cause a segfault if my guess that "element" is a string is wrong
size_t buflen = strlen(e1->element) + 1; // +1 for null terminator
if (!(e2->element = (Following)malloc(sizeof(char) * buflen))) {
printf("not enough memory\n");
}
strcpy(e2->element, e1->element);
e2->next = NULL;
// Link new element with previous element
if (e2prev)
e2prev->next = e2;
e2prev = e2;
}
queue2.error = queue1.error;
queue2.first = e2first;
queue2.last = e2;
Your compiler is warning you that memcpy wants two pointers as first argument. This would be the correct way to copy:
memcpy(&queue1, &queue2, sizeof(queue2));
The above line will overwrite the structure queue1 with the contents of queue2, effectively copying quque2 over queue1.
Often in projects, complex structures are used, e.g., like the one below:
struct opts {
char* server;
char* port;
int protocol;
void* protocol_data;
};
And to free such structures, till today I adopted the routines as below:
void free_proto1(struct opts* opt);
void free_proto2(struct opts* opt);
void free_opts(struct opts** opt) {
free((*opt)->server);
free((*opt)->port);
if ((*opt)->protocol == PROTOCOL1) {
free_proto1(*opt);
}
else if ((*opt)->protocol == PROTOCOL2) {
free_proto2(*opt);
}
else
free((*opt)->protocol_data);
free(*opt);
*opt = NULL;
}
But If I have another struct opts pointer like struct opts* opts2 = opts1, another call to free_opts(&opt2) after calling free_opts(&opt1) would definitely result in a program crash. I know a good habit of coding is to avoid such calls. But is there by any chance, I could detect that the memory is already freed? I am interested in even looking into Process Control Block (That is where I think all the program information resides). Can I scrutinize the PCB structures, before performing a free()'ing operations, so that I can avoid free()'ing the memory twice?
Unfortunately, C has no support for smart pointers like f.e. C++ has.
In C, you always have to be careful to not cause memory leaks.
Anyway, You can f.e. provide another parameter in the manner of reference counting. This has the downside that you need to pass the amount of reference pointers to the allocated memory as argument everytime you call free_opts and the amount have to be fixed, but it is an approach to help you out.
The memory is only freed, if all references have been "pseudo-freed".
All passed reference pointers, except the last one, are just made a null pointer and the pointed memory is in fact not freed until the last reference pointer has been past.
int free_opts (struct opts** opt, int ref) {
static int cnt = 0;
cnt++;
if ( cnt != ref ) {
*opt = NULL;
return 0;
}
free((*opt)->server);
free((*opt)->port);
if ((*opt)->protocol == PROTOCOL1) {
free_proto1(*opt);
}
else if ((*opt)->protocol == PROTOCOL2) {
free_proto2(*opt);
}
else
free((*opt)->protocol_data);
free(*opt);
return 1;
}
Whether the memory is actually freed or not, is indicated by the return value.
You could use a reference counted API, ie: adding a size_t refs field to your struct, and then add a
struct opts* ref_opts(struct opts* opt)
API that will increase ref counter and return opt; finally, renaming free_opts to unref_opts() and only actually free your structure when refs field is 0.
This will expose a known API to take a structure reference and to free it, in a very homogeneous way; it will be users' fault if they do not use it.
When freeing set the pointer to the known invalid value - usually NULL.
Then even if you free more than one time - free ignores NULL pointers.
#RobertSsupportsMonicaCellio and #Federico suggested some reliable methods of preventing the memory free'ing twice. But I feel like the suggestion made by #vll should not be lost in the comments, thus I am summarizing the poster suggestion as an answer.
Another reliable way of keeping track of the pointers is to maintain a list of the allocated addresses, and free them only when they are on the list. Below is the bare minimal implementation:
#include "list.h"
static struct list addr_list;
struct opts* create_opts(void) {
struct opts* opts = (struct opts*) calloc(1, sizeof(struct opts));
if (opts == NULL)
return NULL;
/* Initialize the opts{} */
list_append(&addr_list, opts);
return opts;
}
int free_opts(struct opts* opts) {
if (in_list(&addr_list, opts) == false)
return 0;
/* Free the opts{} */
list_remove(&addr_list, opts);
return 1;
}
Of course, the above implementation simply turns down the request of freeing the structs, which are not created using create_opts(). A partial solution to that can be using flags to enable force cleaning as such. But I hope, someone if at all it is possible will come with some concrete answer.
Thanks to everyone for all the valuable suggestions :)
I have a struct as follows:
typedef struct Node {
void* data;
unsigned long id;
NodePtr next;
NodePtr prev;
} Node;
It is meant to be a node in a linked list ADT. I have 2 different constructors depending on what the Node needs to hold in data. One constructor uses:
NodePtr TempNode;
TempNode = malloc( sizeof(Node) );
/* Other stuff */
TempNode->data = newList();
return (TempNode);
And this seems to work just fine for letting me access that list by returning (List->current->data) where current is a Node pointer in the List Struct
However, I want to make a version of the constructor where (data) points to an int. I've read that I can do this by doing the following
void* ptr;
int x = 0;
*((int*)ptr) = x;
But with the way my constructor is set up, that would mean I have to do something like this?
*((int*)TempNode->data) = 1; // data starts at 1
And this doesn't work. I'm very new to C so I don't understand much of the terminology. I read that dereferencing (using the -> notation?) cannot be done with void*'s, but it seems to work fine in my list version of the constructor. How can I rewrite my other constructor to cast this void* to an int?
I strongly counsel against doing this, but if you really want to use the void * member to hold an integer, you can do:
Node *constructor_int(int n)
{
Node *tmp = malloc(sizeof(*tmp));
/* Other stuff */
tmp->data = (void *)n;
return(tmp);
}
This involves the minimum number of casts and avoids most problems with relative sizes of types.
The obvious, logical way to do it is to allocate an integer for the data member to point at:
Node *constructor_int(int n)
{
Node *tmp = malloc(sizeof(*tmp));
/* Other stuff */
tmp->data = malloc(sizeof(int));
*(int *)temp->data = n;
return(tmp);
}
You just have to remember to free the two memory allocations.
The code should also check that the memory allocations succeeded before using the results.
Let's talk about this
When you do something like
NodePtr TempNode;
TempNode = malloc( sizeof(Node) );
you have asked the library to reseve you some dynamic storage which is big enough for a Node. The initial values of that memory are undefined, so right now the pointer TempNode->data could point anywhere and probably does not point at memory reserved for your use.
When you do
TempNode->data = newList();
you give the pointer a (presumably, as long as newList() does something legal and sensible) valid value;
If instead you do
*((int*)TempNode->data) = 1;
you instruct the compiler to
treat TempNode->Data as a pointer-to-int,
de-reference it and
set the value of what every memory is at the other end to 1 (notice that at no point have you set data itself, just whatever it points at)
But you don't know what it points to! De-referencing it is undefined behavior and strictly a bad thing.
You are always responsible for ensuring that you do not de-reference a pointer unless it points to memory that you are entitled to use.
"How can I make data point to an area I can use?"
I'm not sure if you mean what I'm going to explain below (and it won't be short :P), but if you are asking how you can distinguish the type of the data stored in Node->data, then with that implementation you cannot.
You leave it up to the end-programmer to remember what type of data he has stored into the list (which is not a bad thing btw.. on the contrary, it is the norm). In other words, you trust the end-programmer that he/she will apply the proper casts when say printing the Node->data.
If for some reason you wish to provide a more managed API for your list, you could add one more field in a List struct, for identifying the type of the data stored in your list.
For example...
enum DataType {
DT_INVALID = 0,
DT_PTR
DT_CHAR,
DT_INT,
DT_FLOAT,
DT_DOUBLE,
...
/* not a data-type, just their total count */
DT_MAX
};
#define DT_IS_VALID(dt) ( (dt) > DT_INVALID && (dt) < DT_MAX )
typedef struct List List;
struct List {
enum DataType dt;
Node *head;
};
Of course you are free to support less or more data-types than the ones I listed in the enum, above (even custom ones, say for strings, or whatever you see fit according to your project).
So first you'll need a constructor (or initializer) for a list, something like this...
List *new_list( enum DataType dt )
{
List *ret = NULL;
if ( !DT_IS_VALID(dt) )
return NULL;
ret = malloc( sizeof(List) );
if ( NULL == ret )
return NULL;
ret->dt = dt;
ret->head = NULL;
return ret;
}
and instantiate it, say like this...
int main( void )
{
List *listInt = new_list( DT_INT );
if ( NULL == list ) {
/* handle failure here */
}
Now that you have already stored the intended data-type into the list meta-data, you are free to choose how you will implement the Node constructors. For example, a generic one could look something like this...
int list_add_node( List *list, const void *data )
{
Node *node = NULL;
size_t datasz = 0;
/* sanity checks */
if ( !list || !data || !DT_IS_VALID(list->dt) )
return 0; /* false */
node = malloc( sizeof(Node) );
if ( NULL == node )
return 0; /* false */
/* when data points to mem already reserved say for an array (TRICKY) */
if ( DT_PTR == list->dt ) {
node->data = data;
}
/* when data points to mem reserved for a primitive data-type */
else {
datasz = dt_size( list->dt ); /* implement dt_size() according to your supported data-types */
node->data = malloc( datasz );
if ( NULL == node->data ) {
free( node );
return 0; /* false */
}
memcpy(node->data, data, datasz );
}
/* add here the code dealing with adding node into list->head */
...
return 1; /* true */
}
For DT_PTR (which I flagged as TRICKY in the example) it is more safe to implement a different Node constructor, perhaps accepting 2 extra arguments, lets say elemsz and nelems, so the function can allocate elemsz * nelems bytes for copying the data contents into them, in case data points to an array, a struct or any other non-primitive type. Or you can provide an extra DT_ARR enum value specifically for arrays. You are free to do whatever suits you best.
In any case, for DT_PTR the example above relies on the caller of list_add_node to have properly allocated the passed data, and in general context this is not a good thing at all.
The code is more complicated, but you know the data-type stored in your list. So for at least the primitive data-types you can add say a printing routine that automatically casts its output according to list->dt (for non-primitive data types you should provide support for custom printing routines, usually via callback functions).
You can even take it to the extreme, and move the dt field from List to Node. In that case you implement a list of heterogeneous data in the nodes, but it gets much more complicated and also its rarely useful (if ever).
All this ADT stuff via (void *) pointers have serious performance issues, that's why speed critical implementations utilize (or abuse if you prefer) the pre-processor instead, for this kind of stuff.
I have a generic linked-list that holds data of type void* I am trying to populate my list with type struct employee, eventually I would like to destruct the object struct employee as well.
Consider this generic linked-list header file (i have tested it with type char*):
struct accListNode //the nodes of a linked-list for any data type
{
void *data; //generic pointer to any data type
struct accListNode *next; //the next node in the list
};
struct accList //a linked-list consisting of accListNodes
{
struct accListNode *head;
struct accListNode *tail;
int size;
};
void accList_allocate(struct accList *theList); //allocate the accList and set to NULL
void appendToEnd(void *data, struct accList *theList); //append data to the end of the accList
void removeData(void *data, struct accList *theList); //removes data from accList
--------------------------------------------------------------------------------------
Consider the employee structure
struct employee
{
char name[20];
float wageRate;
}
Now consider this sample testcase that will be called from main():
void test2()
{
struct accList secondList;
struct employee *emp = Malloc(sizeof(struct employee));
emp->name = "Dan";
emp->wageRate =.5;
struct employee *emp2 = Malloc(sizeof(struct employee));
emp2->name = "Stan";
emp2->wageRate = .3;
accList_allocate(&secondList);
appendToEnd(emp, &secondList);
appendToEnd(emp2, &secondList);
printf("Employee: %s\n", ((struct employee*)secondList.head->data)->name); //cast to type struct employee
printf("Employee2: %s\n", ((struct employee*)secondList.tail->data)->name);
}
Why does the answer that I posted below solve my problem? I believe it has something to do with pointers and memory allocation. The function Malloc() that i use is a custom malloc that checks for NULL being returned.
Here is a link to my entire generic linked list implementation: https://codereview.stackexchange.com/questions/13007/c-linked-list-implementation
The problem is this accList_allocate() and your use of it.
struct accList secondList;
accList_allocate(&secondList);
In the original test2() secondList is memory on the stack. &secondList is a pointer to that memory. When you call accList_allocate() a copy of the pointer is passed in pointing at the stack memory. Malloc() then returns a chunk of memory and assigns it to the copy of the pointer, not the original secondList.
Coming back out, secondList is still pointing at uninitialised memory on the stack so the call to appendToEnd() fails.
The same happens with the answer except secondList just happens to be free of junk. Possibly by chance, possibly by design of the compiler. Either way it is not something you should rely on.
Either:
struct accList *secondList = NULL;
accList_allocate(&secondList);
And change accList_allocate()
accList_allocate(struct accList **theList) {
*theList = Malloc(sizeof(struct accList));
(*theList)->head = NULL;
(*theList)->tail = NULL;
(*theList)->size = 0;
}
OR
struct accList secondList;
accList_initialise(secondList);
With accList_allocate() changed to accList_initialise() because it does not allocate
accList_initialise(struct accList *theList) {
theList->head = NULL;
theList->tail = NULL;
theList->size = 0;
}
I think that your problem is this:
You've allocated secondList on the stack in your original test2 function.
The stack memory is probably dirty, so secondList requires initialization
Your accList_allocate function takes a pointer to the list, but then overwrites it with the Malloc call. This means that the pointer you passed in is never initialized.
When test2 tries to run, it hits a bad pointer (because the memory isn't initialized).
The reason that it works when you allocate it in main is that your C compiler probably zeros the stack when the program starts. When main allocates a variable on the stack, that allocation is persistent (until the program ends), so secondList is actually, and accidentally, properly initialized when you allocate it in main.
Your current accList_allocate doesn't actually initialize the pointer that's been passed in, and the rest of your code will never see the pointer that it allocates with Malloc. To solve your problem, I would create a new function: accList_initialize whose only job is to initialize the list:
void accList_initialize(struct accList* theList)
{
// NO malloc
theList->head = NULL;
theList->tail = NULL;
theList->size = 0;
}
Use this, instead of accList_allocate in your original test2 function. If you really want to allocate the list on the heap, then you should do so (and not mix it with a struct allocated on the stack). Have accList_allocate return a pointer to the allocated structure:
struct accList* accList_allocate(void)
{
struct accList* theList = Malloc( sizeof(struct accList) );
accList_initialize(theList);
return theList;
}
Two things I see wrong here based on the original code, in the above question,
What you've seen is undefined behaviour and arose from that is the bus error message as you were assigning a string literal to the variable, when in fact you should have been using the strcpy function, you've edited your original code accordinly so.. something to keep in mind in the future :)
The usage of the word Malloc is going to cause confusion, especially in peer-review, the reviewers are going to have a brain fart and say "whoa, what's this, should that not be malloc?" and very likely raise it up. (Basically, do not call custom functions that have similar sounding names as the C standard library functions)
You're not checking for the NULL, what if your souped up version of Malloc failed then emp is going to be NULL! Always check it no matter how trivial or your thinking is "Ah sher the platform has heaps of memory on it, 4GB RAM no problem, will not bother to check for NULL"
Have a look at this question posted elsewhere to explain what is a bus error.
Edit: Using linked list structures, in how the parameters in the function is called is crucial to the understanding of it. Notice the usage of &, meaning take the address of the variable that points to the linked list structure, and passing it by reference, not passing by value which is a copy of the variable. This same rule applies to usage of pointers also in general :)
You've got the parameters slightly out of place in the first code in your question, if you were using double-pointers in the parameter list then yes, using &secondList would have worked.
It may depend on how your Employee structure is designed, but you should note that
strcpy(emp->name, "Dan");
and
emp->name = "Dan";
function differently. In particular, the latter is a likely source of bus errors because you generally cannot write to string literals in this way. Especially if your code has something like
name = "NONE"
or the like.
EDIT: Okay, so with the design of the employee struct, the problem is this:
You can't assign to arrays. The C Standard includes a list of modifiable lvalues and arrays are not one of them.
char name[20];
name = "JAMES" //illegal
strcpy is fine - it just goes to the memory address dereferenced by name[0] and copies "JAMES\0" into the memory there, one byte at a time.
My goal is to run a API call repeatedly and check for memory leaks.
The API takes in integer input and returns a pointer to the first structure in a linked list of structures as output. Each structure may have struct variables of other types.
In the following code i have tried to represent my problem.
The problem is in callApi() function. I need to dispose of the memory occupied by the structure 'output' that the API() returns. Even if i use free(output) here, it will cause a memory leak because since it points to a linked list of nested structures. (source of info : http://en.wikibooks.org/wiki/C_Programming/Memory_management)
Question:
When leaving exiting callApi() call, will the 'output' nested structure expire when control goes out of the function back to main()? Will it free the entire memory occupied? Please suggest a solution to way to solve this memory leak problem.
Can this problem be overcome with C++?
typedef struct{
int dev_size;
char *dev_name;
dev_stat *next_dev;
mem_stat *mem_info;
} dev_stat
typedef struct{
int mem_capacity;
char *mem_name;
} mem_stat
int main()
{
int input;
int return_val;
int callApi(int);
while(1)
{
return_val=callApi(input);
print return_val;
}
}
int callApi(int ip)
{
//Update: Memory allocation is unnecessary as it is done inside the API() call itself
//dev_stat *output=(dev_stat *)calloc(2,sizeof(dev_stat));
int ret_val;
ret_val=API(ip,&output);
free(output);
output=NULL;
return ret_val;
}
The simple answer is, no, the memory will not "expire" when you exit a function.
The API should provide a way to "free" the returned value, if it is a complex structure. If it doesn't, then traversing the structure yourself and freeing it is probably the only way out.
The first question who is the owner of the structures you are going to free.
It might be that the API returns a pointer to its internal structure, which you must not deallocate (because, for example, it may be shared).
It might be as well that your code is responsible for deallocating the structure itself, but not the other structures that your structure points to. This way you need to just free the returned structure and forget about it.
It might be however that your responsibility is to free the whole object tree starting at the returned structure. In that case it's to be expected that the API has some function which properly deallocates the structure with its descendants for you. If not (which is most likely not the case), you have to free all the resources referenced by your structure, recursively.
You should look up at the APi documentation to find out which if the three cases is your case.
Update:
Explicitly for your case (the whole structure should be deallocated manually), I would use something like that:
void free_mem_stat(struct mem_stat* p)
{
if (!p) return;
free(p->mem_name);
free(p);
}
void free_dev_stat(struct dev_stat* p)
{
// first, clean up the leaves
for(struct dev_stat* curr = p; curr; curr = curr->next_dev)
{
free(curr->dev_name);
free_mem_stat(curr->mem_info);
}
// than, clean up the linked list
for(struct dev_stat* curr = p; curr; /**/)
{
struct dev_stat* next = curr->next_dev;
free(curr);
curr = next;
}
}
int callApi(int ip)
{
int ret_val;
struct dev_stat* output;
ret_val = API(ip, &output);
free_dev_stat(output);
return ret_val;
}
Note that the function like free_dev_stat ought to be provided by the API itself, if the API developers really intend to let the users deallocate their structures.