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++;
}
Related
I have the following structures:
typedef struct block {
char *hash;
char *data;
char *previousHash;
} Block;
typedef struct blockchain {
Block** chain;
size_t length;
} Blockchain;
Along with the following functions:
char* generate_hash(char* toHash) {
return "[ placeholder ]";
}
Block* make_block(char* data, char* previousHash) {
size_t hash_size = 65 * sizeof(char);
size_t data_size = ( 1 + strlen(data)) * sizeof(data);
Block* new_block = malloc(2 * hash_size + data_size);
new_block->data = data;
new_block->previousHash = previousHash;
char toHash[strlen(data) + strlen(previousHash) + 1];
strcpy(toHash, data);
strcat(toHash, previousHash);
new_block->hash = generate_hash(toHash);
return new_block;
}
Block* make_genesis() {
return make_block("Genesis Block", "");
}
Blockchain* make_blockchain() {
Block *blockchain[] = { make_genesis() };
Blockchain* bc = malloc(8 + sizeof(size_t));
bc->chain = blockchain;
bc->length = 1;
return bc;
}
void display_blockchain(Blockchain *bc_ptr) {
for (int i = 0; i < bc_ptr->length; i++) {
printf("Block Number %d\n", i);
printf("\tHash: %s\n", bc_ptr->chain[i]->hash);
}
}
I then call those functions like so:
int main(int argc, char *argv[]) {
Blockchain* my_blockchain = make_blockchain();
display_blockchain(my_blockchain);
Block* new_block = make_block("sdf", "sdf");
display_blockchain(my_blockchain);
return 0;
}
The first time display_blockchain is called, it works as intended. However, the second time it is called, the program crashes due to a segmentation fault. make_block has no access to my_blockchain, so I am not sure why the two would result in different outcomes.
You are using some memory address allocated on stack outside its scope:
Block *blockchain[] = { make_genesis() }; // This is Block** allocated on stack
Blockchain* bc = malloc(8 + sizeof(size_t));
bc->chain = blockchain; // Here you assign the stack address of Block**
bc->length = 1;
return bc;
Then when you access it later, it generates a segmentation fault.
Why doesn't it crash the first time? Well, this is pure coincidence. This is mainly because when the function returns, the memory leftovers are not wiped out. When you call the display function, the function is not so big to overwrite the memory leftovers on the stack, and the stack address in the pointer is actually intact. But if you call a more complex function, like make_block, it will get to overwrite the contents on the stack, thus corrupting the stack address where you would "expect" to find your bc->chain variable.
The solution is that this line Block *blockchain[] = { make_genesis() }; needs to be malloc'd instead.
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;
}
In my binary search tree I want to create a function that can get all words starting with a prefix and store all words in an array called results
this is my tree
struct BinarySearchTree_t
{
char *mot,*def;
struct BinarySearchTree_t *left;
struct BinarySearchTree_t *right;
};
typedef struct BinarySearchTree_t BinarySearchTree;
my function :
size_t findWordsByPrefix(BinarySearchTree* tree, char* prefix, char*** results)
{
BinarySearchTree *tmp;
tmp=tree;
static int size=0;
if (!tmp)
return 0;
else if (strncmp(tmp->mot,prefix,strlen(prefix))==0)
{
(*results)= realloc(*results,(1+size)*sizeof(*(*results)));
(*(*results+size))= malloc(strlen(tmp->mot)*sizeof(char));
strcpy((*results)[size],tmp->mot);
size++;
return (1 + findWordsByPrefix(tmp->left,prefix, &results) + findWordsByPrefix(tmp->right,prefix, &results));
}
else
return (strncmp(tmp->mot,prefix,strlen(prefix))<0)?findWordsByPrefix(tmp->right,prefix, &results):findWordsByPrefix(tmp->left,prefix, &results) ;
}
This function should return a number of words starting with the given prefix.
my problem is that the program crash when it is run , and I don't how to resize my array results
so every time I found a word I should increase the size of the results array .
and I would know how exacly manipulate the pointer of pointer of pointer given in arg of this function (char ***results) : what exactly means?
If I simply compile your code, I get severe compiler warnings including:
1>binarysearchtree.c(98) : warning C4047: 'function' : 'char ***' differs in levels of indirection from 'char ****'
1>binarysearchtree.c(98) : warning C4024: 'findWordsByPrefix' : different types for formal and actual parameter 3
This alone will cause a crash -- you are calling your own function recursively with the wrong arguments.
Next, I believe you need to allocate one more than the length of the string, to hold a copy of a string:
malloc((strlen(tmp->mot) + 1 )*sizeof(char))
Next, you're passing around an array of strings of variable size -- and storing the size in a static variable. It's impossible to know if this will work, so don't do it.
Instead, if you want to use a dynamic array of strings, I suggest extracting out a struct to hold them, like so:
struct ResultTable_t
{
int size;
char **results;
};
typedef struct ResultTable_t ResultTable;
void InitializeResults(ResultTable *p_table)
{
p_table->size = 0;
p_table->results = NULL;
}
void AddResult(ResultTable *p_table, char *result)
{
if (result == NULL)
return;
p_table->size++;
p_table->results = realloc(p_table->results, p_table->size * sizeof(*p_table->results));
p_table->results[p_table->size-1] = malloc((strlen(result) + 1) * sizeof(**p_table->results));
strcpy(p_table->results[p_table->size-1], result);
}
void FreeResults(ResultTable *p_table)
{
if (p_table->results != NULL)
{
int i;
for (i = 0; i < p_table->size; i++)
{
free(p_table->results[i]);
}
free(p_table->results);
}
p_table->size = 0;
p_table->results = NULL;
}
(As an improvement, you might consider using geometric growth instead of linear growth for your table of results.)
Then your function becomes:
size_t findWordsByPrefix(BinarySearchTree* tree, char* prefix, ResultTable *p_table)
{
if (!tree)
return 0;
else if (strncmp(tree->mot,prefix,strlen(prefix))==0)
{
AddResult(p_table, tree->mot);
return (1 + findWordsByPrefix(tree->left,prefix, p_table) + findWordsByPrefix(tree->right,prefix, p_table));
}
else if (strncmp(tree->mot,prefix,strlen(prefix))<0)
{
return findWordsByPrefix(tree->right,prefix, p_table);
}
else
{
return findWordsByPrefix(tree->left,prefix, p_table);
}
}
And you would use it like:
ResultTable results;
InitializeResults(&results);
// Get some prefix to search for.
char prefix = GetSomePrefix();
int size = findWordsByPrefix(tree, prefix, &results);
// Do something with the results
// Free all memory of the results
FreeResults(&results);
Update
If the ResultTable is distasteful for some reason, you can pass the dynamic array and array sizes in directly:
void AddResult(char ***p_results, int *p_size, char *word)
{
if (word == NULL)
return;
(*p_size)++;
(*p_results) = realloc(*p_results, ((*p_size)+1) * sizeof(**p_results));
(*p_results)[(*p_size)-1] = malloc((strlen(word) + 1) * sizeof(***p_results));
strcpy((*p_results)[(*p_size)-1], word);
}
void FreeResults(char ***p_results, int *p_size)
{
int i;
if (p_results == NULL || *p_results == NULL)
return;
for (i = 0; i < (*p_size); i++)
{
free ((*p_results)[i]);
}
free (*p_results);
*p_results = NULL;
*p_size = 0;
}
size_t findWordsByPrefix(BinarySearchTree* tree, char* prefix, char ***p_results, int *p_size)
{
if (!tree)
return 0;
else if (strncmp(tree->mot,prefix,strlen(prefix))==0)
{
AddResult(p_results, p_size, tree->mot);
return (1 + findWordsByPrefix(tree->left,prefix, p_results, p_size) + findWordsByPrefix(tree->right,prefix, p_results, p_size));
}
else if (strncmp(tree->mot,prefix,strlen(prefix))<0)
{
return findWordsByPrefix(tree->right,prefix, p_results, p_size);
}
else
{
return findWordsByPrefix(tree->left,prefix, p_results, p_size);
}
}
and use like:
char **results = NULL;
int tablesize = 0;
// Get some prefix to search for.
char prefix = GetSomePrefix();
int size = findWordsByPrefix(tree, prefix, &results, &tablesize);
// Do something with the results
// Free all memory of the results
FreeResults(&results, &tablesize);
typedef struct {
int count;
int *items;
}set;
set* set_alloc(set *src, int num);
int set_insert(set *s, int num);
int main() {
set *A = NULL;
A = set_alloc(A, 0);
A = set_alloc(A, 1); //this and line below is part of inserting function
A->items[0] = 2;
system("pause");
}
set* set_alloc(set *src, int num) {
if (src == NULL && num == 0) {
set *src = (set*)malloc(sizeof(set));
src->count = 0;
src->items = NULL;
}
else {
src->count = num;
src->items = (int*)realloc(src->items, num*sizeof(int));
}
return src;
}
Code above is able to allocate memory for the array of items inside the set and for the set itself, however, it fails to realloc that array of items.. I could set it a constant size, but I don't really wanna go around this problem because I've had it in previous projects.
Here:
set *src = (set*)malloc(sizeof(set));
you are redeclaring src (in a block scope), you want:
src = malloc(sizeof(set));
I could set it a constant size, but I don't really wanna go around
this problem because I've had it in previous projects.
An alternative to realloc when you don't know the size beforehand is a linked list.
Your function never returns the newly allocated "*src" from function set_alloc, see my comments below, please use the same *src for allocation, and your code should work.
set* set_alloc(set *src, int num) {
if (src == NULL && num == 0) {
set *src = (set*)malloc(sizeof(set)); ***//<--- This pointer is local to if block.***
*//Please Correct code as =>* src = (set*)malloc(sizeof(set));
src->count = 0;
src->items = NULL;
}
else {
src->count = num;
src->items = (int*)realloc(src->items, num*sizeof(int));
}
return src; ***// <-- This is returning the in parameter not the malloced pointer ***
}
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.