So I wrote my 2 structs in a file:
struct _Variable {
char *variableName;
char *arrayOfElements;
int32_t address;
};
typedef struct _Variable Variable;
struct _VariableVector {
int size; // elements full in array
int capacity; // total available elements
Variable *variables;
};
typedef struct _VariableVector VariableVector;
and I also implemented a init method for each:
Variable* initVariable(char *variableName, char *arrayOfElements,
int32_t address) {
Variable* initializedVariable = malloc(sizeof(Variable));
if (initializedVariable != NULL ) {
initializedVariable->variableName = variableName;
initializedVariable->arrayOfElements = arrayOfElements;
initializedVariable->address = address;
return initializedVariable;
} else {
return NULL ;
}
}
VariableVector* initVariableVector() {
VariableVector* initializedVariableVector = malloc(
sizeof(VariableVector));
if (initializedVariableVector != NULL ) {
initializedVariableVector->size = 0;
initializedVariableVector->capacity = VECTOR_INITIAL_CAPACITY;
initializedVariableVector->variables = malloc(
sizeof(Variable) * VECTOR_INITIAL_CAPACITY);
return initializedVariableVector;
} else {
return NULL ;
}
}
now I would like to write a freeVariable(Variable* variable) method and a freeVariableVector(VariableVector* variableVector) method. But I don't know how?
Just call free on the pointer you want to free. As answered in your other nearly identical question.
Related
I am trying to build a program which will function as an assembler, it will be getting file name as command line arguments and translate them to machine code.
The program compiles just fine and runs OK with 1 file name, but when I try to run with several, the error appears after the first iteration.
I think there might be something withe the Clear() function (which flushes out all the data allocated in the previous iteration), but not sure why. Note that this is partial, but as I said, the program will run unless several files are used.
struct symbolStruct { // a structure which is used to absorb info about a tag, its place in memory and related flags
char *name;
int place;
unsigned int isEntry : 1;
unsigned int isData : 1;
unsigned int isExternal : 1;
struct symbolStruct *next;
};
typedef struct { // a structure which is used to absorb info about the operand structure of an instruction line
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;
typedef struct {
unsigned int row : WORD_SIZE;
} int15;
struct MachineCode { // a structure which is used to absorb machine code lines, and their location in the assembly file
unsigned int row : WORD_SIZE;
unsigned int line;
OperandType *structure;
struct MachineCode *next;
};
struct DataCode { // a structure which is used to absorb data and string elements (signed numbers and ascii characters)
unsigned int row : WORD_SIZE;
struct DataCode *next;
};
struct Operation { /* the main operation structure, contains pointers to all used lists, the ic and dc counters, the
current line number which is dealt with and the error flag. */
unsigned int ic;
unsigned int dc;
struct symbolStruct *externHead; // a pointer to a linked list of extern tags used in the assembly file, and their locations
struct symbolStruct *symbolHead; // a pointer to a linked list of all tags
struct DataCode *dataHead; // a pointer to a linked list of all data/string elements
struct MachineCode *machineHead; // a pointer to a linked list of all machine code rows
int linenumber;
unsigned int errorflag : 1; // raised in case of an error which triggered a warning
};
#include "header.h"
void FirstRun(struct Operation*, char *);
void DataUpdate(struct symbolStruct*,int);
void SecondRun(struct Operation *, char *);
void Clear(struct Operation *);
int main(int argc, char *argv[]) {
int i;
struct Operation programCore = {0,0,NULL,NULL,NULL,NULL,0,0};
for(i=1;i<argc;i++) {
char *fn = argv[i];
FirstRun(&programCore,fn);
DataUpdate(programCore.symbolHead,programCore.ic+INSTRUCTION_OFFSET);
SecondRun(&programCore,fn);
Clear(&programCore);
programCore.symbolHead = programCore.externHead = programCore.dataHead = programCore.machineHead = NULL;
}
if(argc < 2) {
fprintf(stderr,"No files selected.\n");
}
return 0;
}
/*Used to empty the linked lists and allocated memory after the program has finished one iteration. */
void Clear(struct Operation *programCore) {
/*f(pointer name) is there to hold a pointer to the allocated memory which is about to be flushed. */
struct MachineCode *machineHead = programCore->machineHead, *fMachineHead;
struct DataCode *dataHead = programCore->dataHead, *fDataHead;
struct symbolStruct *externHead = programCore->externHead, *fExternHead;
struct symbolStruct *symbolHead = programCore->symbolHead, *fSymbolHead;
while(machineHead != NULL) {
fMachineHead = machineHead;
machineHead = machineHead->next;
if(fMachineHead->structure != NULL) {
if(fMachineHead->structure->numOfOperands == 2)
free(fMachineHead->structure->secondOperand);
if(fMachineHead->structure->numOfOperands > 0)
free(fMachineHead->structure->firstOperand);
free(fMachineHead->structure);
}
free(fMachineHead);
}
while(dataHead != NULL) {
fDataHead = dataHead;
dataHead = dataHead->next;
free(fDataHead);
}
while(externHead != NULL) {
fExternHead = externHead;
externHead = externHead->next;
free(fExternHead->name);
free(fExternHead);
}
while(symbolHead != NULL) {
fSymbolHead = symbolHead;
symbolHead = symbolHead->next;
free(fSymbolHead->name);
free(fSymbolHead);
}
programCore->ic = programCore->dc = programCore->linenumber = programCore->errorflag = 0;
}
You do not free and nullifying the linked lists in the context struct (programCore). I suspect you are then using pointers to freed memory blocks.
This line only copies the pointer:
struct MachineCode *machineHead = programCore->machineHead;
The while() loop is not clearing programCore->machineHead
To fix it, run directly on the head:
while(programCore->machineHead != NULL)
{
...
}
Well, by getting rid of
if(fMachineHead->structure->numOfOperands == 2)
free(fMachineHead->structure->secondOperand);
if(fMachineHead->structure->numOfOperands > 0)
free(fMachineHead->structure->firstOperand);
I have managed to solve the error, but now I am getting a new one -
main.c:242:13: error: request for member ‘symbolHead’ in something not a structure or union
main.c:242:38: error: request for member ‘externHead’ in something not a structure or union
main.c:243:13: error: request for member ‘dataHead’ in something not a structure or union
main.c:244:13: error: request for member ‘machineHead’ in something not a structure or union
Referring to the next line -
programCore.symbolHead = programCore.externHead = programCore.dataHead = programCore.machineHead = NULL;
Is there a problem with the way I wrote that? (Obviously yes, but I just don't see it).
Changed the clear() function again and it seems to be working fine now.
/*Used to empty the linked lists and allocated memory after the program has finished one iteration. */
void Clear(struct Operation *programCore) {
/*f(pointer name) is there to hold a pointer to the allocated memory which is about to be flushed. */
struct MachineCode *machineRowPointer = programCore->machineHead, *fMachineRow;
struct DataCode *dataRowPointer = programCore->dataHead, *fDataRow;
struct symbolStruct *externSymbolPointer = programCore->externHead, *fExtern;
struct symbolStruct *symbolPointer = programCore->symbolHead, *fSymbol;
if(machineRowPointer != NULL) {
while(machineRowPointer != NULL) {
if(machineRowPointer->structure != NULL)
free(machineRowPointer->structure);
fMachineRow = machineRowPointer;
machineRowPointer = machineRowPointer->next;
free(fMachineRow);
}
programCore->machineHead = NULL;
}
if(dataRowPointer != NULL) {
while(dataRowPointer != NULL) {
fDataRow = dataRowPointer;
dataRowPointer = dataRowPointer->next;
free(fDataRow);
}
programCore->dataHead = NULL;
}
if(externSymbolPointer != NULL) {
while(externSymbolPointer != NULL) {
fExtern = externSymbolPointer;
externSymbolPointer = externSymbolPointer->next;
free(fExtern->name);
free(fExtern);
}
programCore->externHead = NULL;
}
if(symbolPointer != NULL) {
while(symbolPointer != NULL) {
fSymbol = symbolPointer;
symbolPointer = symbolPointer->next;
free(fSymbol->name);
free(fSymbol);
}
programCore->symbolHead = NULL;
}
programCore->ic = programCore->dc = programCore->linenumber = programCore->errorflag = 0;
}
I hope I have not oversimplified my code, but what I am basically trying to do is to find the existence of an element in a container, and return the pointer to it.
I have structures like
typedef struct INHs{
int ID;
} INHs;
typedef struct sub_container{
INHs** list_inh;
int nb_list;
} sub_container;
typedef struct container {
sub_container* cont;
int nb_elem;
} container;
And then in my main method I have a container allocated (I will leave it out for simplicity, and a given ID; and for now I won't to iterate over the sub-containers to find my target INHs structure).
INHs** test_INH = NULL;
INHs** return_val = NULL;
int ID = 10;
container* cont; //allocated on all memory
for (uint n=0; !test_INH && n<container_nb_elem; n++){
return_val = find_ptr(&cont[n], ID, &test_INH);
}
INHs** find_ptr(sub_container* sub_cont, int ID, INHs*** test){
INHs** res = NULL;
for (uint i=0; !res && i<sub_cont->nb_list; i++){
if (sub_cont->list_inh[i].ID == ID) {
(*test) = &(sub_cont->list_inh[i]);
res = &(sub_cont->list_inh[i]);
}
return res;
}
I know I don't need both a return value to my element and another one as a function parameter, but these are the two versions I have tried. I don't know what I am doing wrong but valgrind crashes telling me that either "test_INH" or "result_val" are non-initialized, although I am setting them on null.
Does someone see what I am missing here?
typedef struct INHs{
int id;
} INHs;
typedef struct sub_container{
INHs **ptrs;
int nb_list;
} sub_container;
typedef struct container {
sub_container *items;
int nb_elem;
} container;
int main(void)
{
INHs **found = NULL;
int id = 10;
container *cont; //allocated on all memory
for (uint n=0; n < cont->nb_elem; n++){
found = find_ptr( &cont->items[n], id);
if (found) break; /* found it! */
}
if(found) {
/* do something useful with *found ... */
}
return 0;
}
INHs **find_ptr(sub_container *sub_cont, int id)
{
for (uint i=0; i < sub_cont->nb_list; i++){
if (sub_cont->ptrs[i]->id != id) continue;
return &sub_cont->ptrs[i];
}
return NULL;
}
BTW: I find the array of pointers to one integer structures rather strange.
Are these structures all malloc()d separately?
So when I call the following function I get a seg fault:
void destroyVariableVector(VariableVector* variableVector) {
if (variableVector) {
free(variableVector->variables); // <== Seg Fault here
free(variableVector);
}
}
And this is what my structs look like:
struct _Variable {
char *variableName;
char *arrayOfElements;
int type;
int32_t address;
};
typedef struct _Variable Variable;
struct _VariableVector {
int size; // elements full in array
int capacity; // total available elements
Variable *variables;
};
typedef struct _VariableVector VariableVector;
and here are their init methods:
Variable* initVariable(char *variableName, char *arrayOfElements,
int32_t address, int type) {
Variable* initialVariable = malloc(sizeof(*initialVariable));
if (initialVariable != NULL ) {
initialVariable->variableName = strdup(variableName);
initialVariable->arrayOfElements = strdup(arrayOfElements);
initialVariable->address = address;
initialVariable->type = type;
}
return initialVariable; // may be NULL
}
VariableVector* initVariableVector() {
VariableVector* initialVariableVector = malloc(sizeof(VariableVector));
if (initialVariableVector != NULL ) {
initialVariableVector->size = 0;
initialVariableVector->capacity = VECTOR_INITIAL_CAPACITY;
initialVariableVector->variables = malloc(
sizeof(Variable) * VECTOR_INITIAL_CAPACITY);
}
return initialVariableVector;
}
Can anyone explain how I am getting a seg fault when I call my destroyVariableVector() method???
Here is the code that calls the above functions:
VariableVector* variableVector = initVariableVector();
// add some variables to variableVector
writeOutVariables(variableVector, outputFilePointer);
destroyVariableVector(variableVector);
where the method writeOutVariables looks like:
void writeOutVariables(VariableVector *variableVector, FILE *outputFilePointer) {
// write out all variables within the variableVector to the output file
int variableVectorSize = variableVector->size;
int i = 0;
// start from the first variable in the varaibleVector to the last variable
while (i < variableVectorSize) {
// 0 = label; 1 = variable ascii string; 2 = variable number array;
int currentType = variableVector->variables->type;
if (currentType == 1) {
writeToFileASCIICharArrayInReverseOrder(
variableVector->variables->arrayOfElements,
outputFilePointer);
i++;
} else if (currentType == 2) {
char currentNumberArray[MAXIMUM_LINE_LENGTH + 1]; // + 1 for terminating char
strcpy(currentNumberArray,
variableVector->variables->arrayOfElements);
char* currentNumber = strtok(currentNumberArray, " ,\t\n");
while (currentNumber != NULL ) {
// you have not yet reached the end of the numberArray
int integer = atoi(currentNumber);
writeToFileIntegerAs32bits(integer, outputFilePointer);
currentNumber = strtok(NULL, " ,\t\n");
}
i++;
} else {
i++;
}
variableVector->variables++; // move on to next variable
}
}
In writeOutVariables, you're incrementing variableVector->variables to iterate through your list. However, this because it's a pointer, you're incrementing the actual value and hence moving the pointer beyond the end. Then, when you try to free variables, you're actually freeing memory that wasn't previously malloced.
Instead, initialize a pointer to variableVector->variables inside writeOutVariables so you don't clobber that pointer.
void writeOutVariables(VariableVector *variableVector, FILE *outputFilePointer) {
Variable *tmpVariables = variableVector->varaibles;
// The original code
// ...
tmpVariables++;
}
#include<stdio.h>
struct test_ {
char *device_name;
char *path_name;
};
typedef struct test_ test_t;
struct capabilities_ {
test_t tab[3];
int enable;
};
static test_t table[3] = {
{ "first", "john"},
{ "second", "mike"},
{ "third:", "vik" },
};
int main()
{
struct capabilities_ cap;
//cap.tab = table; ???
return 0;
}
I have a static array with the value, which I want to assign/copy to the same type/sized variable under the structure to table to cap.tab. Could you please help how to do that?
To do it at runtime, you can use user9000's approach, or something like this:
for (i = 0; i < 3; i++)
cap.tab[i] = table[i];
Or, convert your tab to use a pointer to test_t instead of array of test_t.
struct capabilities_ {
test_t *tab;
int enable;
};
int main()
{
struct capabilities_ cap;
cap.tab = table;
printf("%s\n", cap.tab[1].device_name);
return 0;
}
Or, if you are trying to do it at initialization, use one of the following:
struct capabilities_ cap = {
{
{ "first", "john" },
{ "second", "mike" },
{ "third:", "vik" },
},
1
};
Or this,
struct capabilities_ cap = {
{
table[0],
table[1],
table[2],
},
1
};
If you want to copy the strings, and not just the pointer to the strings, you'll need to allocate memory for each string in the target capabilities struct. Here is one way to do that
for (int i = 0; i < sizeof(table) / sizeof(test_t); i++)
{
size_t device_name_length = strlen(table[i].device_name);
size_t path_name_length = strlen(table[i].path_name);
size_t target_device_length = device_name_length + 1; // + 1 for null terminator
size_t target_path_length = path_name_length + 1; // + 1 for null terminator
cap.tab[i].device_name = (char*) malloc( target_device_length );
cap.tab[i].path_name = (char*) malloc( target_path_length );
strncpy_s(cap.tab[i].device_name, target_device_length, table[i].device_name, device_name_length);
strncpy_s(cap.tab[i].path_name, target_path_length, table[i].path_name, path_name_length);
}
If you don't care to make a deep copy, you can use the shallow copy mechanism shown by user9000 to just copy the pointers to the strings.
Also, if you use the mechanism above, don't forget to free if your capabilities is going to go out of scope and no longer be used :)
You can do it like so:
memcpy(cap.tab, table, sizeof (test_t) * (sizeof(table) / sizeof(test_t)));
This is just the same mechanism used in copying a string to another. Since you have the table size known, you can just do:
memcpy(cap.tab, table, 3 * sizeof(test_t));
The equivalent method of copying characters is like:
memcpy(str, str1, sizeof(char) * 4); // copy 4 of str1 into str
Sorry I'm new to memory allocation and structure (so most probably it's some silly thing I've missed). I've got the following code which is core dumping on Solaris. I'm not also sure how to add more elements later (should I realloc memory?)
enum field_type
{
FLD_STRING,
FLD_SHORT
};
typedef struct {
long id;
char *name;
field_type type;
void *value;
} myStruct_t ;
typedef struct {
long id;
const char *name;
field_type type;
const char *descr;
} myStructDef_t;
myStructDef_t Alldef[] =
{
{0, "FirstField", FLD_STRING, "First Field Of Structure"},
{1, "SecondField", FLD_STRING, "Second Field Of Structure"},
{-1}
};
int main()
{
myStruct_t *p_struct;
char tmp[100] = {'\0'};
long id = 0;
if(NULL == (p_struct= structAlloc(1024)))
{
print("Failed allocating memory\n");
return 0;
}
sprintf(tmp, "Test Adding value");
addValueToStruct(p_struct, id, (void *)tmp);
}
myStruct_t *structAlloc(long size)
{
myStruct_t *tmp = (myStruct_t *) calloc(size, sizeof *tmp);
if(NULL != tmp)
tmp->id = -1;
return tmp;
}
int addValueToStruct(myStruct_t *p_struct, long id, (void *)value)
{
myStruct_t *bkStruct = p_struct;
myStructDef_t *def = NULL;
if(-1 == getIdDefinition(def, id))
{
printf("Failed to find definition for id [%ld]", id);
return -1;
}
// Core dumping on 1st line below
bkStruct->id = def->id;
sprintf(bkStruct->name, "%s", def->name);
bkStruct->type = def->def->type;
if(FLD_SHORT == bkStruct->type)
memcpy(bkStruct->value, value, sizeof(*(short *)value));
else if(FLD_STRING == bkStruct->type)
memcpy(bkStruct->value, value, sizeof(*(char *)value));
return 0;
}
int getIdDefinition(myStructDef_t *def, long id)
{
myStructDef_t *AllDefsTmp = Alldef;
bool found = false;
while( -1 != AllDefsTmp->id)
{
if(id == AllDefsTmp->id)
{
def = AllDefsTmp;
found = true;
break;
}
AllDefsTmp ++;
}
if(!found)
return -1;
return 0;
}
Thanks :)
myStructDef_t *def = NULL;
if(-1 == getIdDefinition(def, id))
{
printf("Failed to find definition for id [%ld]", id);
return -1;
}
// Core dumping on 1st line below
bkStruct->id = def->id;
Calling GetIdDefinition(def, id) will fill in def within the that function, but won't change the value within the addValueToStruct function - you need a double pointer (in C) or reference (in C++), so that you can change the value of def itself. (Or you could of course just return the value you found, instead of -1 or 0 return value).