I am trying to figure out how / the best way to read pointer chains from memory then save them to the heap. To learn this I am using this random single player game where I already managed to track down the static address of the entity list. I was also able to successfully read all required values from that list so I know my problem is figuring out how to save those values to memory for later use. So my goal with this question is to now figure out how to correctly save those entities values into my program. I am also fairly new to storing data to the heap so if you know of a vastly superior way please let me know. Anyways when I show my memory reading source code there will be a comment that says "Save the values to the heap here" which denotes where the following code will be called.
struct entity {
int *valueOne;
float *valueTwo;
};
static struct entity *entityArray[24];
void heapStruct()
{
int intTest = 3;
float test = 21.4;
struct entity aEntity2;
aEntity2.valueOne = &intTest;
aEntity2.valueTwo = &test;
struct entity *aEnt = (struct entity *) malloc(sizeof(struct entity));
aEnt->valueOne = &intTest;
aEnt->valueTwo = &test;
entityArray[0] = aEnt;
printf("IntValue:%i HexValue%x StructHex:%x \n", *entityArray[0]->valueOne, entityArray[0]->valueOne, entityArray[0]);
printf("FloatValue:%f HexValue%x \n", *entityArray[0]->valueTwo, entityArray[0]->valueTwo);
}
The above code is obviously not exactly what I will use but its a test case I have written to make sure everything works in theory. My thought process is that I will read addresses that store the values I need from each entity then store those as pointers in my entity struct. The reason they need to be pointers is because the values can change so storing static values makes it all pointless while storing the actual memory address of where the values lie will give it a dynamic approach so that I can always use up to date info.
Anyways after initially reading the addresses from memory I will use malloc to save my entity struct to the heap before then saving a pointer to that heap memory space where my struct lives in a global 'private' array. My temporary print statements above shows how I could then read these entities values. Of course in the above example I am saving variables that live on the stack so it wont actually work when called from any where else but the real version should work since the values I will be reading are stored on the heap ie pointers to the heap memory where my entities values live.
All that being considered I do have one actual problem which is I can't figure out which is how to save the variable addresses using ReadProcessMemory. When I run the following code valueOne and valueTwo return the actual value at that memory location instead of the memory address its self. I also tried making valueOne and valueTwo pointers but that obviously did nothing since ReadProcessMemory did not return a pointer it only returned the value.
int main()
{
DWORD pid;
printf("Enter the process id: ");
scanf("%d", &pid);
printf("\n");
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); //PROCESS_ALL_ACCESS gives all access, PROCESS_VM_READ gives reading access
if(hProcess == NULL) {
printf("OpenProcess Failed GetLastError: %d \n", GetLastError());
getchar();
getchar();
return pressToClose(EXIT_FAILURE);
}
const uintptr_t processBaseAddress = 0x00400000;
const uintptr_t baseOffset = 0x191FCC;
const uintptr_t arrayOffset = processBaseAddress + baseOffset;
uintptr_t entityArray;
ReadProcessMemory(hProcess, (LPCVOID) arrayOffset, &entityArray, sizeof(int), NULL);
printf("BaseArrayAddress:%x entityArray:%x \n", arrayOffset, entityArray);
for(int i=0; i<4; i++) {
uintptr_t entityObject;
int valueOne;
float valueTwo;
BOOL rpmEntityObject = ReadProcessMemory(hProcess, (LPCVOID) (entityArray + (i * 0x4)), &entityObject, sizeof(int), NULL);
ReadProcessMemory(hProcess, (LPCVOID) (entityObject + 0x00EC), &valueOne, sizeof(int), NULL);
ReadProcessMemory(hProcess, (LPCVOID) (entityObject + 0x0028), &valueTwo, sizeof(float), NULL);
if(rpmEntityObject == FALSE) {
printf("Exit the array! \n");
printf("ReadProcessMemory 1 failed. GetLastError = %d \n", GetLastError());
break;
}
printf("i:%i EntityObject:%x \n", i, entityObject);
printf("i:%i ValueOneAddress:%x ValueOne:%i \n", i, (entityObject + 0x00EC), valueOne);
printf("i:%i ValueTwoAddress:%x ValueTwo:%f \n", i, (entityObject + 0x0028), valueTwo);
// Save the values to the heap here;
printf("\n");
}
printf("Press any key to close... \n");
getchar();
getchar();
return 0;
}
Since I know what the problem is I have to ask is it possible to fix? Is it possible for me to save pointers to the actual addresses at which the values are located inside of my program or do I have to make a massive loop that calls all of this code multiple times a second (in order to keep the values inside my array of structs updated)? I can't seem to figure out how to actually read the address of the valueOne and valueTwo since reading the memory at (entityObject + 0x0028) means I have already gone too far but I don't know how I can back up since I have to read the address at
(entityArray + (i * 0x4)) first because that contains a pointer to the actual entity object. But after I read that I can't make any more read calls without the values I want are not stored as a pointer which means (entityObject + 0x0028) is there actual address. I also can't just make a pointer to those values by doing...
int *pointerValueOne;
pointerValueOne = (entityObject + 0x00EC);
So I am just at a loss of how to get a pointer to the address (entityObject + 0x00EC) when that's where the value is stored. Anyways the following is my terminals output.
Enter the process id: 17268
BaseArrayAddress:591fcc entityArray:caee078
i:0 EntityObject:c0ec5a0
i:0 ValueOneAddress:c0ec68c ValueOne:103 ValueOneAddress:67
i:0 ValueTwoAddress:c0ec5c8 ValueTwo:76.000000
i:1 EntityObject:c0ed278
i:1 ValueOneAddress:c0ed364 ValueOne:100 ValueOneAddress:64
i:1 ValueTwoAddress:c0ed2a0 ValueTwo:88.000000
i:2 EntityObject:c0eb480
i:2 ValueOneAddress:c0eb56c ValueOne:100 ValueOneAddress:64
i:2 ValueTwoAddress:c0eb4a8 ValueTwo:105.900002
i:3 EntityObject:c0edf50
i:3 ValueOneAddress:c0ee03c ValueOne:100 ValueOneAddress:64
i:3 ValueTwoAddress:c0edf78 ValueTwo:175.000000
Press any key to close...
Also I know I can do stuff like cleaning up my print statements, changing const to #define, and other small things but I am not going to focus on making everything look super nice till I get the core mechanics working ei saving a pointer to the memory addresses of entities values. Of course if you see any issues with my future heap implementation please let me know! (Also I am talking about the idealized scenario I mentioned at the top since the code is completely wrong at this time.)
Related
I have an assignment in C that basically asks for some sort of interface/database for a supposed animal shelter, and we were given these 2 structures:
typedef struct age
{
int years, months;
}age;
typedef struct pet
{
int id;
char* sex;
char* breed;
age* pet_age;
}pet;
The interface has to have several functions, like adding a new pet (in our case dogs specifically), removing based on ID, searching for all pets of the same breed and changing the name of a breed entirely, and it all has to be done dynamically using a pet* array as well as the malloc and realloc functions. The entries have to be written in a file and also read from it, but that's something I'll figure out after I figure out how to handle the functions regarding my dynamic array first.
To get to the point, I am having trouble understanding how to scan/reference an instance's pet_age. I've tried it a myriad different ways but I don't understand what's wrong, really. The program crashes/exits after I scan the months element.
Here is the insertion function I have implemented thus far. While not correct, the main source file still compiles.
void addPet(pet *p){
if(i=1){ //First time activation check.
p=malloc(k*sizeof(p));
if(!p){
printf("\nUnable to allocate memory...");
exit(0);
}
}
p[i].sex = malloc(sizeof(char)*1);
p[i].breed = malloc(sizeof(char)*20);
p[i].pet_age =malloc(sizeof(int)*2);
p[i].id = i; //Autogenerated ID
printf("\n%d\n", p[i].id);
printf("Insert pet's breed:"); //Scan breed
scanf("%s", p[i].breed);
printf("Insert pet's sex:"); //Scan sex
scanf("%s", p[i].sex);
printf("Insert pet's age in years:"); //Scan years
scanf("%d", p[i].pet_age->years);
printf("\n%d\n", p[i].pet_age->years);
printf("Insert pet's age in months:"); //Scan months
scanf("%d", p[i].pet_age->months);
printf("\n%d\n", p[i].pet_age->months);
i++; //Incrementing counter
if(i==k){
k+=10;
p=realloc(p, k*sizeof *p); //Size check
}
}
For now there is a basic initialization in the event that this is the first insertion. Then I allocate memory for each element of the structure (to the best of my understanding), and scan every element with a scanf (I pasted some printf checks to see what was actually scanned). Then at the end I increment the i counter, followed by a size check to allocate 10 more places for the array in the event that i==k.
For the sake of continuity, here is my main function as well (basic menu and all):
int i=1; //Counter
int k=10; //Default max entries
int main(int argc, char *argv[]) {
FILE *fp;
int choice;
pet *petarray;
//Menu that lists every option.
while(1){ //Endless loop that ends only if you choose to exit through the 5th option.
printf("\n\n Menu:");
printf("\n=========");
printf("\n1. Insert information for a new pet.");
printf("\n2. Delete a pet record based on pet's ID.");
printf("\n3. Search a pet record based on pet's breed.");
printf("\n4. Update pet's breed name.");
printf("\n5. Exit.\n\n");
scanf("%d", &choice);
switch(choice)
{
case 1:
addPet(petarray);
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
printf("Exiting program...");
exit(0);
}
}
return 0;
}
Apologies if this seems amateur, I'm quite the rookie and still learning. Thanks in advance.
It compiles, but don't you get a long list of warnings? If you don't, you should turn on warnings.
But let's have a look.
void addPet(pet *p)
{
if (i = 1)
You are not comparing (global!) i to 1 here. You are assigning to it. This if statement can only take the true path because of that. When you assign to i, the result of the assignment is the value you assign, so you are testing if (1) here. You want to take this path only if i is 1, I guess, so you should use if (i == 1).
{ //First time activation check.
p = malloc(k * sizeof(p));
Well, it is every time, but we have fixed that now. What do you want p to be, here? An array of k pets? That is not what you are allocating memory for. You are allocating space for k times sizeof(p) and since p is a pet *p, that means you are allocating space for k pointers to pets. Not pets. That, of course, is a problem since p is a pointer to pet and not a pet **. You have most likely allocated too little memory here.
This, unfortunately, is usually not something you will get a warning about. You can give malloc() any size, and it will give you that amount of memory. If you asked for the wrong amount, you get the wrong amount. I think you wanted malloc(k * sizeof *p) here. That allocates space for k of the kind of objects p points to, and that means you can use p as an array of k of that type. You do it the right way when you realloc() later, so this is probably just a quick mistake, but it can easily destroy everything at runtime.
p[i].sex = malloc(sizeof(char) * 1);
p[i].breed = malloc(sizeof(char) * 20);
Two issues here. First, are you sure that p has an entry i? If you fixed the allocation above, then the p you allocated the first time has room for k pets, but this could be any p we have called the function with, so we don't know about this one at all. There is absolutely no guarantee that it is valid to access p[i]. Your reliance on the two global variables will generally make this very dodgy; you simply cannot assume that the function is called with the specific pointer you allocated memory for a bit earlier.
Second, for the string allocation, there are a few red flags as well. sizeof(char) is always 1, so you don't need it. It isn't wrong, really, it just looks odd. And are you absolutely sure that you are allocating enough memory? For p[i].sex I find it highly unlikely. You are getting space for exactly one char. If you only want one char, then that is fine, but you you should probably declare sex a char instead of a char *. If you plan to put a string in p[i].sex, then it will have to be the empty string and nothing longer, because you have only room for the '\0' terminal in a buffer of length 1.
With
p[i].pet_age = malloc(sizeof(int) * 2);
it might technically work, but I don't think the standard guarantees it. You are allocating space for a struct age, and that struct holds two int. They will align the right way, so there shouldn't be any padding, and therefore it should work, but it is flaky as hell.
If you want to allocate space for a struct, then do that. malloc(sizeof(struct age)) gets the job done. Even better, gets the type from the variable you are allocating space for:
p[i].pet_age = malloc(sizeof *(p[i].pet_age));
If p[i].pet_age is a struct age *, then *(p[i].pet_age) is a struct age, and it is the size of that we want.
Then we read in the data.
printf("Insert pet's breed:"); //Scan breed
scanf("%s", p[i].breed);
Here we can have a buffer overflow.
printf("Insert pet's sex:"); //Scan sex
scanf("%s", p[i].sex);
Here we are guaranteed one, because we need to write the terminal zero into sex after we put the data there.
printf("Insert pet's age in years:"); //Scan years
scanf("%d", p[i].pet_age->years);
printf("\n%d\n", p[i].pet_age->years);
printf("Insert pet's age in months:"); //Scan months
scanf("%d", p[i].pet_age->months);
printf("\n%d\n", p[i].pet_age->months);
Since scanf needs to store the data it reads somewhere, it needs a pointer to where it should put it. You are providing integers. (Your compiler definitely should have warned you here). You should use &p[i].pet_age->years to store an integer in p[i].pet_age->years, and the same for months.
Then we get to what I think is probably the worst error in the code.
if (i == k)
{
k += 10;
p = realloc(p, k * sizeof *p); //Size check
}
I'm not going to comment on the global variables again, but rather the local variable. This realloc potentially destroys the memory that p pointed at. I don't care that it can return NULL and you don't check; I doubt that this is happening in your program, but someone called addPet with a pointer, and they have no way of knowing if that pointer is valid again after calling. They have to consider it lost. It won't be freed if addPet() doesn't free it (and it doesn't), and they cannot safely do it themselves. The new memory you allocate doesn't get back to the caller in any way. Assigning to the local variable in addPet() doesn't affect any caller's variable. This realloc() is dangerous. The caller will absolutely lose the existing memory and has no way of obtaining the new memory.
Any of these issues can be the cause of your current problem; the others can be the cause of future problems.
I made a simple base converter and the very first thing it does is it gets a string from the user. I wanted the string to be dynamic, so I did this:
char *getStr() {
char *str = NULL;
/*LOOP THAT USES getc() TO SAVE CHARS INTO THE STRING AND GROWS IT USING realloc() IF NEEDED*/
return str;
}
int main() {
char *str;
str = getStr();
//SOME STUFF HAPPENS HERE WITH THE str. IT REMAINS THE SAME LENGTH.
free(str) //IS THIS THE RIGHT PLACE TO FREE IT?
}
So, is free() in the right place here? I understand that since both str pointers point to the same address it should work, right? Also, by the way, how does free() know where to stop deallocating, when it only has the first address?
This may be pretty obvious, but I wanna make sure.
In your example, this is the right place for it.
The simplest free are called when you are just no need for the data anymore.
The tricky part in my experience is when things don't go as planned, or when your program can exit with multiple ways.
Take a look at this dummy program that has absolutely no real purpose.
A program that takes an integer, if this integer has a value superior to 10, the program will add 1 to it. If not, it will exit the whole program with exit (1)
static void add_one_to_num(int *num)
{
if (*num < 10)
{
free(num);
exit(1);
}
*num = *num + 1;
}
int main()
{
int *num;
num = malloc(sizeof(int));
printf("Enter a number higher than 10: ");
scanf("%d", num);
add_one_to_num(num);
printf("num: %d\n", *num);
free(num);
return (0);
}
In this program, we might exit at the function add_one_to_num so you need to free that pointer in that place.
By writing more and more programs you will get the hang of it, because it's actually very logical and not at all chaotic (It could be a pain in the neck for large programs to track down all allocated memories throughout all the functions the pointers are passed to ).
just make sure to free when you longer need the data, or when something changes the natural flow of your program.
I have a simple code:
#include <stdio.h>
#include <stdlib.h>
int main(void){
char *str = (char *) malloc(4*sizeof(char));
int i;
for(i = 0; i < 64; i ++)
printf("%d, %ld, %d, %c\n", i, (long) &(str[i]), (int) str[i], str[i]);
return 0;
}
I allocate a memory into str using malloc() which is available to save 4 letters in str[0], ..., str[3]. I know that malloc() does not initialize its memory while calloc() does.
This program prints str[i] with i, address of str[i], value of str[i], letter of str[i], in order. (I use 64-bits Ubuntu, hence address is long type.)
As expected, addresses are quite different for every time I run the program. But I wonder that why str[24], str[25], and str[26] are -31, 15, 2, repectively, and other values are all 0 as you can see below:
(Note that without option -O0 gives same result.)
How can memory has same sequence (0,0,...,0,-31,15,2,0,0,...) even though only first four 0s in that sequence are allocated and others are out of care?
As you just have pointed out, malloc() doesn't initialize memory (by the way, even if it would, starting from str[4*sizeof(char)] it wouldn't be initialized because it's already out of range).
This means that you print out data that was at this memory location before. It's undefined behaviour so strictly unpredictable.
The fact that you see the same value, could be a coincidence. But if repeatable, and always with the same values, it most probably traces of the what the OS and the standard library did to initialize the environment of your process before giving control to your main().
There is a related SO question about uninitialized variables on stack. The principle of unitialized data giving access to remanent value is similar here, only that it's on the heap.
Here an experiment : a small programme to try to show you the kind of thing that could happen (attention: it's implementation dependent):
int main() {
int i;
// first part ================
char *p=(char*)malloc(100); // allocate a region in memory
for (i=0; i<100; i++) // initialize it to 0
p[i]=0;
strcpy (p+10, "Christophe"); // put some value womewhere in the middle
free(p); // release memory
// second part ============
char *q= (char*)malloc(100); // innocently allocate new memory
// and display its content
printf ("%ld==%ld ? %c%c%c\n", (long) p, (long)q, q[10],q[11], q[12]);
return 0;
}
So you could imagine that something like the first part of this code could be run during the initialization sequence of the standard library (could be at startup of the programme, or the first time you call malloc()).
Here a live demo of this code.
I am having problems updating an array globally from a while loop, as expalined below. Please note that I can only use functionality from C 95 and before. Anyhelp would be greatly appreciated! Full paste bin http://pastebin.com/ss6VgTCD
Declared at the Top of my program
int data_count, i;
float *x_values, *y_values;
float x[100],y[100];
In My main function my arrays are created using the code below:
printf("\nPlease Enter How Many Data Points You Wish To Enter: \n");
scanf("%d", &data_count);
x_values=(float*)calloc(data_count,sizeof(*x_values));
y_values=(float*)calloc(data_count,sizeof(*y_values));
if (x_values==NULL) {
printf("Error! Memory Could Not Be Allocated. ");
exit(0);
}
File read function to import previously entered data, the function is getting the correct data and displays the correct data points in my debugging line printf("%12f%12f\n", x_values[i], y_values[i]); however is only locally updating x_values and y_values as these imported data can not be seen by the rest of the program. How can I globally update the array?
void file_read(void) {
store = fopen ("j:/StoredValues.txt", "r");
if (store == NULL )
printf("\nError: Failed To Open Previous Data File - Program Will Continue Anyway\n");
else {
printf("\nSuccess: Data From Previous Run Imported\n");
i=0;
do {
fscanf ( store, "%f,%f\n", &x[i], &y[i]);
x_values = x;
y_values = y;
printf("%12f%12f\n", x_values[i], y_values[i]);
i=i+1;
} while (!feof(store));
fclose(store);
}
}
p.s. Ive only coded in C for 2 weeks so simple is nice :)
In the first code block you've allocated memory and saved the pointer to it in 'x_values'.
In the second block you change 'x_values' to point to the 'x' array. The 'x' array already has memory allocated to it for 100 floating point values.
You will no longer have a pointer to the allocated memory after the assignment.
Any data stored there is no longer accessible since you no longer have a pointer to it.
edit:
Here's a suggested replacement for the file_read() routine:
void file_read(void) {
store = fopen ("j:/StoredValues.txt", "r");
if (store == NULL )
printf("\nError: Failed To Open Previous Data File - Program Will Continue Anyway\n");
else {
printf("\nSuccess: Data From Previous Run Imported\n");
float* px;
float* py;
px = x_values;
py = y_values;
while (!feof(store))
{
fscanf ( store, "%f,%f\n", px, py);
printf("%12f%12f\n", *px, *py );
px++;
py++;
}
fclose(store);
}
}
Edit 2:
Menu choice 2 will display the content of x_values. If file_read() places the content in the x array then you can't display it using option 2. You also can't copy the content of the x array to x_values since x_values doesn't exist yet.
You need to create a storage area for your data before you try to read it in.
To do that you need to store the count of how many points are in the file.
Also consider:
The user enters 10 points and you allocate space for 10.
Then the user wants to enter new data and wants to enter 12.
You now have to free() and alloc() to get space for the extra two.
x_values = x;
y_values = y;
This causes x_values and y_values to point at the statically allocated arrays instead of the data you allocated dynamically for them. So after this assignment, the dynamic data now sits alone and isolated in your RAM as a memory leak, with no reference to it from your program.
I do not work with C directly much and a basic language nuance just set me back and I would like to understand it better so I can avoid it in the future.
I am using the Queue implementation found at the following link.
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=9202&lngWId=3
It's a pretty common queue where values are pushed and popped. (FIFO) But for some reason the last value that I push onto the queue sets all values in the queue with the same value.
I started with the following code.
Queue q;
queue_init(&q);
for (int i=0;i<10;i++) {
MyData *in_md;
in_md->mNumber = i;
queue_push(&q, in_md);
MyData *h = (MyData *)q.head->data;
MyData *t = (MyData *)q.tail->data;
NSLog(#"in_md: %i", in_md->mNumber);
NSLog(#"h->mNumber: %i", h->mNumber);
NSLog(#"t->mNumber: %i", t->mNumber);
if (q.head->link) {
MyData *l = (MyData *)q.head->link->data;
NSLog(#"l->mNumber: %i", l->mNumber);
}
}
But I found that when I popped the values off the number value was 9 for each instance. I thought I had some pointer bug and tried to fix it for a while. I thought that since I declared in_md inside of the block of the for loop it would be a unique instance with a unique memory address. Eventually updated the code to the following...
Queue q;
queue_init(&q);
for (int i=0;i<10;i++) {
void *data = malloc(sizeof(MyData)); // key change
MyData *in_md = (MyData *)data;
in_md->mNumber = i;
queue_push(&q, data);
MyData *h = (MyData *)q.head->data;
MyData *t = (MyData *)q.tail->data;
NSLog(#"in_md: %i", in_md->mNumber);
NSLog(#"h->mNumber: %i", h->mNumber);
NSLog(#"t->mNumber: %i", t->mNumber);
if (q.head->link) {
MyData *l = (MyData *)q.head->link->data;
NSLog(#"l->mNumber: %i", l->mNumber);
}
}
Now the ensures that a new instance is created because malloc is used and I cast it to a variable I can set the int value. This creates the output appears as I expect.
I assume this is how C is supposed to work but I did not expect it. Normally in other languages like Java, C# and even JavaScript declaring a variable within a block would create a new instance of the variable which is what I expected here. But that is not the case.
What is happening in this case?
In your code:
You created a pointer:
MyData *in_md;
and without reserving memory for that pointer (that's what the malloc does in your second code block) you assing values to it's members:
in_md->mNumber = i;
You were basically accessing undefined memory. In your case the value was '9' but you could have gotten an application crash as well.
In your second code block you allocated memory for that pointer and then stored it in the queue - that's the right way.
Keep in mind that you need to deallocate the memory using the free() method before you finally release the queue.
Declaring a pointer does create the pointer, but not the pointee. You still need to initialize the pointer (just like you would need to initialize any other variable), but in the case of a pointer, it needs to be initialized to a memory address, which can be done via the use of new (C++) or malloc (C) to allocate memory (it is also possible to assign the memory address of an existing variable via &).
It is generally good programming practice to combine declaration with initialization. Ensuring that you never use:
Type identifier;
And always use:
Type identifier = initializing_expression;
Will ensure that you don't run into such issues and will save you quite a bit of pain. Note that this is not all that different from other languages (in Java, the language forbids the use of uninitialized variables, altogether, while in JavaScript declaring without initializing will result in it having a value of undefined).
Your second implementation is indeed the way to go.
The part that I think you are getting hung up on is that doing "MyData *in_md;" will indeed make a "new instance" in a sense, but it won't make a new instance of MyData, it makes a new instance of a MyData pointer. A pointer doesn't do you very much good though until it actually points at something useful, hence the malloc call.
So where in Java you would have MyData in_md = new MyData() it will allocate space for MyData automatically, but in C you have MyData *in_md = (MyData*)malloc(sizeof(MyData)); bueause you have much lower-level control of memory. After that, you can work with the object just like you would in Java or C#. The only other thing to remember is that in Java, if memory allocation were to fail, it would probably throw you a nice error, but that is not the case in C, so it may be a good idea to make sure that in_md is not NULL, depnding on the application. Finally, C lacks garbage collection, so it is important to make sure you free() the item that you malloc'ed once you dequeue it.
Queue q;
queue_init(&q);
for (int i=0;i<10;i++) {
MyData *in_md = (MyData *)malloc(sizeof(MyData));
in_md->mNumber = i;
queue_push(&q, (void*)in_md);
MyData *h = (MyData *)q.head->data;
MyData *t = (MyData *)q.tail->data;
NSLog(#"in_md: %i", in_md->mNumber);
NSLog(#"h->mNumber: %i", h->mNumber);
NSLog(#"t->mNumber: %i", t->mNumber);
if (q.head->link) {
MyData *l = (MyData *)q.head->link->data;
NSLog(#"l->mNumber: %i", l->mNumber);
}
}