i'm trying to find the most efficient way to use the 'free' command in a program I made. Basically there are several structers, the first is called Operation. Here's how it's defined -
struct Operation {
unsigned int ic;
unsigned int dc;
struct symbolStruct *externHead;
struct symbolStruct *symbolHead;
struct DataCode *dataHead;
struct MachineCode *machineHead;
int linenumber;
};
It has several pointers to other structers, let's take machineHead for example.
struct MachineCode {
unsigned int row : WORD_SIZE;
unsigned int line;
OperandType *structure;
struct MachineCode *next;
};
And OperandType looks like this -
typedef struct {
unsigned int numOfOperands : 2;
unsigned int addrMethSou : 2;
unsigned int addrMethDest : 2;
unsigned int operation : 4;
unsigned int extraWords : 2;
char *firstOperand;
char *secondOperand;
} OperandType;
What I want to do is to free the strings "firstOperand" and "secondOperand" in structure (which is in machineHead ) and then to free machineHead itself, I tried to write it down using the following code -
void clear(struct Operation *op) {
struct MachineCode *mh = op->machineHead, *fmh;
while(mh != NULL) {
fmh = mh;
mh = mh->next;
free(fmh->structure->firstOperand);
free(fmh->structure->secondOperand);
free(fmh->structure);
free(fmh);
}
But the program crashes in runtime. Is there an elegant way to do it or do I have to make a pointer varibale of every type in order to clear the memory?
Related
I've one solid structure and another structure with pointers. The purpose of program is to assign: solid structure to structure with pointers and access each solid structure member using other structure pointer.
I've problem statement: as two structure member as not symmetric, when i assign solid structure address to structure with pointers, member pointer initialization go bad and crash the system.
Does anyone have any approach to find a solution for this problem in an optimized way?
----------------------------------------------------------------------- program -----------------------------
#include <stdio.h>
#include <string.h>
#include <stddef.h>
/* ===================== Binding Structure ================================= */
typedef struct
{
char id;
}tmodel;
typedef struct
{
char id;
}tbrand;
typedef struct
{
char id;
}tcommercialRef;
typedef struct
{
char id;
}tserialnum;
typedef struct
{
tmodel *smodel;
tbrand *sbrand;
tcommercialRef *scommref;
tserialnum *sslnum;
}tmetadata;
typedef struct
{
tmetadata *smetadata;
}tlink;
typedef struct
{
tlink *slink;
}trefernce;
typedef struct
{
char id[10];
int ttl;
int tss;
trefernce *sref;
}telectrical;
/* ===================== Application Strucuture ==============================*/
void filldata(telectrical *elec);
typedef struct
{
tmodel smodel;
tbrand sbrand;
tcommercialRef scommref;
tserialnum sslnum;
}Ymetadata;
typedef struct
{
Ymetadata smetadata;
}slink;
typedef struct
{
slink glink;
}refernce;
typedef struct
{
char id[10];
int ttl;
int tss;
refernce grefernce;
}gtelectrical;
//solid strucutre object
gtelectrical obj;
//structure pointer object
telectrical *elec = {0};
/* =============================== main.c =================================== */
int main()
{
printf("test");
//static void **p = (void *)&elec;
obj.tss = 55;
obj.ttl = 100;
obj.grefernce.glink.smetadata.smodel.id = 5;
obj.grefernce.glink.smetadata.sbrand.id = 6;
obj.grefernce.glink.smetadata.scommref.id = 7;
obj.grefernce.glink.smetadata.sslnum.id = 8;
elec = (telectrical *)&obj;
//elec structure -> sref pointer goes bad as it's not same type as "grefernce"
//*p = (void *)&obj;
//static long x = (long) offsetof( telectrical, sref);
//(long) offsetof(struct telectrical, sref);
//*(*p + x) = obj.grefernce.glink.smetadata.;
elec->id[0] = 0;
elec->id[1] = 1;
elec->id[2] = 2;
elec->ttl = 5;
elec->tss = 10;
elec->sref->slink->smetadata->sslnum->id = 4;
elec->sref->slink->smetadata->sbrand->id = 1;
elec->sref->slink->smetadata->scommref->id = 2;
elec->sref->slink->smetadata->smodel->id = 3;
//filldata(elec);
printf("------");
printf("%d\n",elec->sref->slink->smetadata->sslnum->id);
printf("%d\n",elec->sref->slink->smetadata->sbrand->id);
printf("%d\n",elec->sref->slink->smetadata->scommref->id);
printf("%d\n",elec->sref->slink->smetadata->smodel->id);
return 0;
}
/* //////////////////////////////////////// user scope ////////////////////////////// */
void filldata(telectrical *pelec)
{
pelec->id[0] = 0;
pelec->id[1] = 1;
pelec->id[2] = 2;
pelec->ttl = 5;
pelec->tss = 10;
//pelec->sref->slink->smetadata->sslnum->id = 4;
//pelec->sref->slink->smetadata->sbrand->id = 1;
//pelec->sref->slink->smetadata->scommref->id = 2;
//pelec->sref->slink->smetadata->smodel->id = 3;
}
You are not assigning memory for the pointers to other struct present inside another struct. Here is something which might help you in multi-level memory allocation and assignment:
#include<stdio.h>
#include<stdlib.h>
typedef struct A
{
int i;
}A_Node;
typedef struct B
{
A_Node *A_ptr;
}B_Node;
typedef struct C
{
B_Node *B_ptr;
}C_Node;
int main(void)
{
//ACCESSING-MANIPULATING A USING B
B_Node B_obj;
B_obj.A_ptr=malloc(sizeof(*(B_obj.A_ptr)));
(B_obj.A_ptr)->i=192;
A_Node A_obj=*(B_obj.A_ptr); //For checking if the allocation is successful and good
printf("%d\n",A_obj.i);
//ACCESSING-MANIPULATING A USING C
C_Node C_obj;
C_obj.B_ptr=malloc(sizeof(*(C_obj.B_ptr))); //allocating space for struct of B using C object
(C_obj.B_ptr)->A_ptr = malloc(sizeof(*((C_obj.B_ptr)->A_ptr))); //allocating space for struct of A using B Struct for which space was allocated in previous step by C struct
((C_obj.B_ptr)->A_ptr)->i=876;
A_obj=*((C_obj.B_ptr)->A_ptr); //For checking if the allocation is successful and good
printf("%d\n",A_obj.i);
return 0;
}
Read the code and ask if there are any doubts, in the similar way this multi-level struct-inside-struct can be created (though it would be ugly).
I am trying to allocate space inside a struct. This struct contains information of a network packet.
The structure:
struct STRUCT_SVC_ROOM_CREATE
{
PacketHeader Header;
unsigned char TitleLength;
char* RoomTitle = new char[TitleLength];
short SuddenFactor;
short GameModeFactor;
unsigned char Password[4];
int MaxMen;
};
See this two lines of code
unsigned char TitleLength;
char* RoomTitle = new char[TitleLength];
1st -> The length of text (1 byte)
2nd -> The text itself (TitleLength bytes)
And this is how I create the struct based into another.
STRUCT_SVC_ROOM_CREATE* RoomCreate = (STRUCT_SVC_ROOM_CREATE*)pHeader;
pHeader is another struct, this contains all the information. Then I put into another struct to get the right data location.
But it doesnt work. So the question: How to allocate space correctly and build the struct char* with the size specified in TitleLength?
You shouldnt initialise the object inside the struct definition.
struct STRUCT_SVC_ROOM_CREATE
{
PacketHeader Header;
unsigned char TitleLength;
char* RoomTitle;
short SuddenFactor;
short GameModeFactor;
unsigned char Password[4];
int MaxMen;
};
void someFunction()
{
STRUCT_SVC_ROOM_CREATE* foo = new STRUCT_SVC_ROOM_CREATE;
foo->TitleLength = 10;
foo->RoomTitle = new char[foo->TitleLength];
}
Here is the requested class implementation (not tested):
class SVC_ROOM_CREATE{
private:
PacketHeader Header;
char* RoomTitle;
short SuddenFactor;
short GameModeFactor;
unsigned char Password[4];
int MaxMen;
public:
SVC_ROOM_CREATE(PacketHeader packet_header, int length, short sud_factor, short gm_factor, unsigned char pwd[], int max)
{
Header = packet_header;
RoomTitle = new char[length];
SuddenFactor = sud_factor;
GameModeFactor = gm_factor;
memcpy( Password, pwd, sizeof(Password));
MaxMen = max;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
PacketHeader Header;
unsigned char bar[4] = "pas";
int TitleLength = 10;
int SuddenFactor = 1;
int GameModeFactor = 2;
int MaxMen = 15;
SVC_ROOM_CREATE* foo = new SVC_ROOM_CREATE(Header, TitleLength, SuddenFactor, GameModeFactor, bar, MaxMen);
return 0;
}
I have searched through many of the answers on here and have implemented a few changes based on that, but am getting a EXC_BAD_ACCESS error when calling the qsort function. My IDE is pointing to the return in my qsort compare function as the problem. I know I am allocating memory properly for all the elements as I can print the strings with no problem if I omit the call to qsort. Could someone point me in the right direction?
My structs, to see how deep I am navigating:
typedef struct {
unsigned int siteId;
unsigned int tableTypeId;
unsigned int surMatId;
unsigned int strucMatId;
char *streetAve;
unsigned int neighbourhoodId;
char *neighbourhoodName;
unsigned int ward;
char *latitude;
char *longitude;
} Entries;
typedef struct {
int size;
Entries **entry;
} PicnicTable;
typedef struct {
Table *tableTypeTable;
Table *surfaceMaterialTable;
Table *structuralMaterialTable;
NeighbourHoodTable *neighborhoodTable;
PicnicTable *picnicTableTable;
} DataBase;
extern DataBase *DB;
Entries **ent = DB->picnicTableTable->entry;
qsort(ent,DB->picnicTableTable->size-1, sizeof(Entries*), cmpfunc); typedef struct {
unsigned int siteId;
unsigned int tableTypeId;
unsigned int surMatId;
unsigned int strucMatId;
char *streetAve;
unsigned int neighbourhoodId;
char *neighbourhoodName;
unsigned int ward;
char *latitude;
char *longitude;
} Entries;
typedef struct {
int size;
Entries **entry;
} PicnicTable;
typedef struct {
Table *tableTypeTable;
Table *surfaceMaterialTable;
Table *structuralMaterialTable;
NeighbourHoodTable *neighborhoodTable;
PicnicTable *picnicTableTable;
} DataBase;
extern DataBase *DB;
This is what the call looks like:
Entries **ent = DB->picnicTableTable->entry;
qsort(ent,DB->picnicTableTable->size-1, sizeof(Entries*), cmpfunc);
And the compare function is:
int cmpfunc(const void *a, const void *b) {
Entries *left = *(Entries**)a;
Entries *right = *(Entries**)b;
return strcmp(left->neighbourhoodName, right->neighbourhoodName);
}
The picnicTableTable, and Entry are initialized after this malloc:
DB->picnicTableTable = malloc(sizeof(PicnicTable));
DB->picnicTableTable->entry = malloc(numEntries*sizeof(Entries)+1);
DB->picnicTableTable->size = numEntries;
while ((c=fgetc(IN)) != EOF) {
if (c == ',' && row > 0) {
switch (column) {
case 0: neighbourhoodName = copyToChar(buff, begin, i);
...
}
copyToChar take a slice of the buffer and allocates memory then returns a pointer to a value that I assign:
char * copyToChar(const char * buff, int begin, int end) {
char *temp = malloc(end - begin + 1);
int j = 0;
for (int i = begin; i < end; i++, j++)
temp[j] = buff[i];
temp[j] = '\0';
return temp;
}
And the array is populated after I iterate through each row in a file (this is just one entry):
DB->picnicTableTable->entry[row]->neighbourhoodName = malloc(strlen(neighbourhoodName)*sizeof(char)+1);
The values of a->neighbourhoodName are NULL, which confuses me. Doesn't qsort pass two values from the array to the compare function?
Thanks for your time!
Beware. You declare entry to be a pointer to pointers (pointing to first element of an array of pointers)
typedef struct {
int size;
Entries **entry;
} PicnicTable;
but initialize it as a mere dynamic array, that is a pointer to first element of an array of Entrys in:
DB->picnicTableTable->entry = malloc(numEntries*sizeof(Entries)+1);
If you want an array of pointers to speed up qsort, you should build it separately:
typedef struct {
int size;
Entries *entry;
Entries **pentry;
} PicnicTable;
DB->picnicTableTable->entry = malloc(numEntries*sizeof(Entries)+1);
DB->picnicTableTable->pentry = malloc(numEntries*sizeof(&Entries)+1);
for (int i=0; i<=numEntries; i++) { // initialize the array of pointers
pentry[i] = entry + i;
}
Currently the definition of cmpfunc is not coherent with your initialization of DB->picnicTableTable->entry.
To explain more, I have two structures-'first' and 'second' having common variables 'jack' and 'jill'. I want to print jack via a pointer based on if-else condition.
I understand at the time of printing I have to typecast the void pointer. But whether the pointer points to struct a or b is decided on run time.
It is a basic C code. How to overcome this?
Code
#include <stdio.h>
int main(void)
{
typedef struct one
{
int jack;
float jill;
}a;
typedef struct two
{
int jack;
float jill;
char something;
int something1;
}b;
a first;
b second;
void *z;
if(1)
{
a* z;
z = &first;
printf("First one");
}
else
{
b* z;
z = &second;
printf("Second one");
}
printf("%d\n", z->jack);
return 0;
}
Error
prog.c:36:17: warning: dereferencing 'void *' pointer printf("%d\n", z->jack); prog.c:36:17: error: request for member 'jack' in something not a structure or union
You get a compiler warning since the compiler does not understand z->jack since z is a void * (note that the declarations a* z and b* z are not valid outside the scope of the if and else block).
To overcome this you can use a function printJack as shown in the following listing:
#include <stdio.h>
typedef struct one
{
int jack;
float jill;
}a;
typedef struct two
{
int jack;
float jill;
char something;
int something1;
}b;
void printJack(void *pStruct, int type)
{
switch (type)
{
case 1:
printf("jack: %d\n", ((a *)pStruct)->jack);
break;
default:
printf("jack: %d\n", ((b *)pStruct)->jack);
break;
}
}
/*
** main
*/
int main(void)
{
a first;
b second;
void *z;
first.jack = 5;
second.jack = 4892;
printJack(&first, 1);
printJack(&second, 0);
z = &first;
printJack(z, 1);
return (0);
}
I've written code like this often and experienced a lot of trouble with it. Not at the time of implementing, since you are knowing what you are typing at that moment but let's say a few years later if you need to extend your code. You will miss a few places where you cast from void * to a * or b * and you'll spend a lot of time debugging what's going on...
Now I'm writing things like this in the following way:
#include <stdio.h>
typedef struct header
{
int jack;
float jill;
} h;
typedef struct one
{
struct header header;
/* what ever you like */
}a;
typedef struct two
{
struct header header;
char something;
int something1;
/* and even more... */
}b;
void printJack(void *pStruct)
{
printf("jack: %d\n", ((struct header *)pStruct)->jack);
}
/*
** main
*/
int main(void)
{
a first;
b second;
void *z;
first.header.jack = 5;
second.header.jack = 4892;
printJack(&first);
printJack(&second);
v = &first;
printJack(v);
return (0);
}
As you've noticed I have declared a new struct header which covers the the common parts of struct one and struct two. Instead of casting the void * to either a * or b * a "common" cast to struct header * (or h *) is done.
By doing so you can easily extend the "common attribtues" of the structs or you can implement further structs using this header and function printJack still will work. Additionally there is no need for attribute type anymore making is easier to call printJack. You can even change the type of jack without needing to change it in various places within your code.
But remember that struct header needs to be the first element of the structs you use this mechanism. Otherwise you will end up with a few surprises since you are using memory which does not contain the data of the struct header...
I have called a function with seven parameters from main
find_sync(es_data + (loop_count * size) + chunk_bytes_counter,
size - chunk_bytes_counter, &sync_index, &flag,
&sync_length, &chunk_bytes_counter, &total_bytes_counter);
in function.c:
void find_sync(char data[], size_t size, unsigned int *sync_index, int *flag, unsigned int *sync_length, unsigned int *chunk_bytes_counter, unsigned int *total_bytes_counter)
prototype in header file:
extern void find_sync(char data[], size_t size, unsigned int *sync_index, int *flag, unsigned int *sync_length, unsigned int *bytes_counter, unsigned int *total_bytes_counter);
Now, my question is, how can i declare all these 7 parameters in a structure, so that i can only pass one structure variable.
Begin by declaring the struct:
struct find_sync_parameters {
char* data;
size_t size;
unsigned int *sync_index;
int *flag;
unsigned int *sync_length;
unsigned int *bytes_counter;
unsigned int *total_bytes_counter;
}
Then change your function signature either to:
void find_sync(struct find_sync_parameters param)
Or to
void find_sync(struct find_sync_parameters *param)
In the first case the whole struct will be pushed onto the stack before transferring control to find_sync. On the second case only a pointer to the struct (stored elsewhere) will be pushed.
There are advantages and drawbacks in each one. When passing a pointer note that the function can change the contents (this can be positive: for returning values directly inside the struct; also can be negative: the caller cannot be sure if its data were changed or not). If the struct is too big (not your case), then pushing everything onto the stack can take a significant amount of time and become a performance hit.
Inside the function you use it either with '.' (dot, the first case) or '->' (arrow, the second case) operator.
To call it:
struct find_sync_parameters p = { ... };
find_sync(p); // first case
find_sync(&p); // second case
If you find it annoying to type struct find_sync_parameters everytime you can define a new type with typedef:
typedef struct find_sync_parameters find_sync_parameters;
Or in one line (struct and typedef definitions):
typedef struct find_sync_parameters {
...
} find_sync_parameters;
Or even without struct name (anonymous struct)
typedef struct {
...
} find_sync_parameters;
In this last case you cannot reference the struct itself inside the struct (the case, for example, with linked list nodes).
Just put in structure .
struct pars_t
{
char data[];
size_t size; unsigned int *sync_index;
int *flag; unsigned int *sync_length;
unsigned int *bytes_counter;
unsigned int *total_bytes_counter;
} pars;
and then call foo (pars_t par)
You can create a struct (and typedef it at the same time, to make it usable without saying "struct" every time) like so:
typedef struct _find_sync_str{
char* data;
size_t size;
unsigned int *sync_index;
int *flag;
unsigned int *sync_length;
unsigned int *bytes_counter;
unsigned int *total_bytes_counter;
} find_sync_str
Then you can list the function as:
void find_sync(find_sync_str f);
I am going to suggest:
struct find_sync_struct {
char* data;
size_t size;
unsigned int sync_index;
int flag;
unsigned int sync_length;
unsigned int bytes_counter;
unsigned int total_bytes_counter;
};
Change the input argument of find_sync to:
void find_sync(struct find_sync_struct* strPtr);
Call the function using:
struct find_sync_struct str;
// Set str.data to something suitable.
// ....
find_sync(&str);
Here is a simple example demonstrating how to pass a structure to a function:
#include<stdio.h>
#include<conio.h>
//-------------------------------------
struct Example
{
int num1;
int num2;
}s[3];
//-------------------------------------
void accept(struct Example *sptr)
{
printf("\nEnter num1 : ");
scanf("%d",&sptr->num1);
printf("\nEnter num2 : ");
scanf("%d",&sptr->num2);
}
//-------------------------------------
void print(struct Example *sptr)
{
printf("\nNum1 : %d",sptr->num1);
printf("\nNum2 : %d",sptr->num2);
}
//-------------------------------------
void main()
{
int i;
clrscr();
for(i=0;i<3;i++)
accept(&s[i]);
for(i=0;i<3;i++)
print(&s[i]);
getch();
}