How to free char** array that allocated in calling function from main? - c

this is the function that i am calling from main:
char** readTokens(char *userInput, const char *seperator)
{
char** c;
char line1[512],line2[512];
int wordCount = 0;
int index;
char* tmp;
strcpy(line1, userInput);
for (index=0;line1[index]!='\n';index++);
line1[index]='\0';
strcpy(line2,line1);
tmp = strtok(line1,seperator);
while (tmp!=NULL)
{
tmp=strtok(NULL,seperator);
wordCount = wordCount + 1;
}
if((wordCount) == ERROR)
{
return NULL;
}
c=(char**)malloc(((wordCount)+1)*sizeof(char*));
if (c == NULL)
{
printf("failed to allocate memory.\n");
return NULL;
}
tmp = strtok(line2,seperator);
index=0;
while (tmp!=NULL)
{
c[index]=(char*)malloc((strlen(tmp)+1*sizeof(char)));
if (c[index]==NULL)
{
printf("failed to allocate memory.\n");
return NULL;
}
strcpy(c[index],tmp);
tmp=strtok(NULL,seperator);
index++;
}
c[index] = NULL;//put NULL on last place
return c;
}
And this how i use it in main:
while (fgets(words, sizeof(words), filePointer) != NULL) // this line is a command of reading a line from the file.
{
/*here i am calling the function*/
array = readTokens(words, " ");
theGraph->graphEdges[index_i].sourceVertex = array[ZERO];
theGraph->graphEdges[index_i].destinationVertex = array[ONE];
theGraph->graphEdges[index_i].arcValue = atoi(array[TWO]);
for(index_j = ZERO ; index_j < vertexes ; index_j++)
{
if(theGraph->placeInTableIndex[index_j] == NULL)
{
theGraph->placeInTableIndex[index_j] = array[ZERO];
break;
}
else if(strcmp(theGraph->placeInTableIndex[index_j],array[ZERO]) == ZERO)
break;
}
for(index_j = ZERO ; index_j < vertexes ; index_j++)
{
if(theGraph->placeInTableIndex[index_j] == NULL)
{
theGraph->placeInTableIndex[index_j] = array[ONE];
break;
}
else if(strcmp(theGraph->placeInTableIndex[index_j],array[ONE]) == ZERO)
break;
}
theGraph->graphEdges[index_i+ONE].sourceVertex = array[ONE];
theGraph->graphEdges[index_i+ONE].destinationVertex = array[ZERO];
theGraph->graphEdges[index_i+ONE].arcValue = atoi(array[TWO]);
index_i+= TWO;
//freeTokens(array);
}
I tried to do free to the array in the end of the while but it not work i still have memory leak from this function (valgrind check). i am using this function to free:
void freeTokens(char** tokens)
{
while(*tokens != NULL)
{
*tokens = NULL;
free(*tokens);
*tokens++;
}
tokens = NULL;
free(tokens);
}

You're losing the original value of tokens (the thing you need to free) by incrementing it; then you set it to NULL, then try to free NULL.
Instead:
void freeTokens(char** tokens)
{
char **freeTokens = tokens;
while (*freeTokens != NULL)
{
free(*freeTokens);
*freeTokens = NULL; // not actually necessary, but must happen *after* if at all
freeTokens++;
}
free(tokens);
// tokens = NULL; // accomplishes nothing; doesn't change the caller's version
}

Related

Searching for A SUFFIX in a tree

So, I'm trying to do an impletation of Sharing Suffixes WITHOUT USING UKKONNENS ALGORITHM (don't understand ukkonnens). So basicaly what I'd do is searching for a word in every node that isn't ending. However, when I try to debug it, it returns a negative value. I honestly don't know how to solve it, I made constant breakpoints so it would come out of the loop and not do as many iterations but it just keeps going.
I'm very new to C so for me this is a hard thing and I appreciate all the help.
#include "trie.h"
tree_t create_trie()
{
int i = 0;
tree_t node = (tree_t)malloc(sizeof(struct _node));
for(i = 0; i < 26; i++)
{
node->sons[i] = NULL;
}
node->ending = false;
return node;
}
void delete_trie(tree_t trie)
{
int i = 0;
for(i = 0; i < 26;i++)
{
if(trie->sons[i]!=NULL)
{
delete_trie(trie->sons[i]);
}
else
{
continue;
}
}
free(trie);
}
tree_t put_trie(tree_t trie, char* s)
{
int i = 0;
char* t = s;
tree_t aux = trie;
if(lookup_trie(trie, s))
return trie;
for(i = 0; t[i]!='\0'; i++)
{
int it = (int)((char)tolower(t[i]) - 'a'); //le index
printf("\niterator %d\n", it);
if(aux->sons[it] == NULL)
{
aux->sons[it] = create_trie();
//aux->sons[it]->s = (char *)malloc(sizeof(char*));
//printf("created tree");
}
aux = aux->sons[it];
}
aux->ending = true;
return trie;
}
bool lookup_trie(tree_t trie, char* s)
{
int i = 0;
char* t = s;
tree_t aux = trie;
for(i = 0; i<strlen(t); i++)
{
int it = (int)((char)tolower(t[i]) - 'a'); //le index
if(aux->sons[it] == NULL)
{
return false;
}
aux = aux->sons[it];
}
if(aux->ending)
{
return true;
}
return false;
}
void print_trie(tree_t trie)
{
int i = 0;
for(i = 0; i<26; i++)
{
if(trie->sons[i] == NULL)
{
continue;
}
else
{
printf("%c", ((char)(i) + 'a'));
print_trie(trie->sons[i]);
}
//print_trie(trie->sons[i])
printf("\n");
}
}
tree_t share_word(tree_t trie, tree_t auxiliar, char* s)
{
int x = 0, j = 0; //auxiliar to compare and for variable
printf("Share word debug\n");
/*if(!is_vide(trie))
return (tree_t)NULL;*/
printf("here");
printf("%s\n",s);
for(j=0; j<26; j++)
{
for(x = 0; x < strlen(s); x++)
{
int it = (int)((char)tolower(s[x]) - 'a');
printf("%d\n", it);
//if its null i'm gonna look into other nodes from the first for
if(trie->sons[j] == NULL)
{
continue;
}
if(trie->sons[j] == NULL)
{
break;
}
else if(trie->sons[it] == NULL) //might pose a problem
{
//if the node is empty, we just jump to the next iteration
if(lookup_trie(trie->sons[j], s)) //if the suffix is present, return the subtree
{
printf("Word belongs\n");
auxiliar = trie->sons[j]; //is auxiliar JUST A POINTER?
return auxiliar;
}
else //if not present, go again through the function
{
auxiliar = share_word(trie->sons[j], auxiliar, s);
}
}
else //trie->sons[it] not null
{
printf("iterator not null\n");
if(lookup_trie(trie->sons[it], s+x)) //if the word is present
{
return trie->sons[it];
}
}
}
}
return auxiliar;
}
tree_t put_word(tree_t trie, char *s)
{
int i = 0;
tree_t auxiliar = create_trie();
printf("Beggining\n");
//missing a condition so it doesnt add all the suffixes;
auxiliar = share_word(trie, auxiliar, s);
/*for(i = 0; i < strlen(s); i++)
{
int it = (int)((char)tolower(s[i]) - 'a');
auxiliar = share_word(trie, auxiliar, s + i); //should look for the suffixes;
if(auxiliar->sons[it] != NULL )
{
if(trie->sons[it] == NULL)
{
trie->sons[it] = create_trie();
trie->sons[it] = auxiliar;
return trie;
}
}
else
{
printf("Auxiliar null\n");
trie->sons[it] = create_trie(); //proceeds to the next iteration by creating the node
}
//}
trie = trie->sons[it];
}*/
return trie;
}
bool is_vide(tree_t trie)
{
int i =0;
for(i =0; i <26;i++)
{
if(trie->sons[i] != NULL)
{
return false;
}
else
{
return true;
}
}
return true;
}
bool leads_leaf(tree_t trie, char *s)
{
int i = 0;
tree_t aux = trie;
for(i = 0; i < strlen(s); i++)
{
int it = (int)((char)tolower(s[i]) - 'a');
aux = aux->sons[it];
if(i == (strlen(s) - 1) && aux->ending)
{
return true;
}
else
{
return false;
}
}
return false;
}
int main()
{
tree_t tree = create_trie();
tree = put_trie(tree, "abcd");
tree = put_word(tree, "decd");
delete_trie(tree);
return 0;
}
I tried testing putting a string in a single way (abcd) and then searching the string (decd), which would add d, e, and when it would go for c it would find the node of the first strings that leads to c -> d -> '\0'. However, it sometimes just keeps veryfing the same letter (d) and doesn't add it or it just never goes to the next (e).
I think there is a problem with the function put_word and how it calls the share suffixes multiple times.

Cant insert Node to binary tree

I am trying to insert Node to Binary tree. This is my function for creating Node (rest is done).
void BVSCreate_function(TNodef *rootPtr, function_save token) {
TNodef *newPtr = malloc(sizeof(struct tnodef));
if (newPtr == NULL) {
fprintf(stderr, "99");
return;
}
TNodef init;
string initStr;
initStr.str = NULL;
initStr.length = 0;
initStr.alloc = 0;
newPtr = &init;
newPtr->content = &initStr;
newPtr->leftPtr = NULL;
newPtr->rightPtr = NULL;
newPtr->return_type = token.ret_value;
newPtr->parameters = token.param_count;
strCpyStr(newPtr->content, token.content);
rootPtr = newPtr;
}
void BVSInsert_function(TNodef *rootPtr, function_save token) {
if (rootPtr == NULL) {
BVSCreate_function(rootPtr, token);
} else {
if ((strCmpStr(token.content, rootPtr->content)) < 0) {
BVSCreate_function(rootPtr->leftPtr, token);
} else
if ((strCmpStr(token.content, rootPtr->content)) > 0) {
BVSCreate_function(rootPtr->rightPtr, token);
}
}
}
When TNodef and function_save are structs:
typedef struct {
string *content;
int param_count;
int ret_value;
} function_save;
typedef struct tnodef {
string *content;
struct tnodef *leftPtr;
struct tnodef *rightPtr;
int parameters;
int return_type;
} TNodef;
Where string is defined as this struct:
typedef struct {
char *str; // content of string
int length; // length of string
int alloc; // amount of memory allocated
} string;
strCpystr function :
int strCpyStr(string *s1, string *s2) {
int len2 = s2->length;
if (len2 > s1->alloc) {
if (((s1->str) = (char *)realloc(s1->str, len2 + 1)) == NULL) {
return 1;
}
s1->alloc = len2 + 1;
}
strcpy(s1->str, s2->str);
s1->length = len2 + 1;
return 0;
}
I am trying to create a node in binary tree and put there information from struct function_save.
But when I try to print this tree after insert it shows me that tree is still empty.
Your code in BVSCreate_function has undefined behavior because:
newPtr = &init; discards the allocated node and instead uses a local structure that will become invalid as soon as the function returns.
newPtr->content = &initStr; is incorrect for the same reason: you should allocate memory for the string too or possibly modify the TNodeDef to make content a string object instead of a pointer.
Function BVSInsert_function does not return the updated root pointer, hence the caller's root node is never updated. You could change the API, passing the address of the pointer to be updated.
There is also a confusion in BVSInsert_function: it should call itself recursively when walking down the tree instead of calling BVSCreate_function.
Here is a modified version:
/* Allocate the node and return 1 if successful, -1 on failure */
int BVSCreate_function(TNodef **rootPtr, function_save token) {
TNodef *newPtr = malloc(sizeof(*newPtr));
string *newStr = malloc(sizeof(*content));
if (newPtr == NULL || newStr == NULL) {
fprintf(stderr, "99");
free(newPtr);
free(newStr);
return -1;
}
newStr->str = NULL;
newStr->length = 0;
newStr->alloc = 0;
newPtr->content = newStr;
newPtr->leftPtr = NULL;
newPtr->rightPtr = NULL;
newPtr->return_type = token.ret_value;
newPtr->parameters = token.param_count;
strCpyStr(newPtr->content, token.content);
*rootPtr = newPtr;
return 1;
}
int BVSInsert_function(TNodef **rootPtr, function_save token) {
if (*rootPtr == NULL) {
return BVSCreate_function(rootPtr, token);
} else {
if (strCmpStr(token.content, rootPtr->content) < 0) {
return BVSInsert_function(&rootPtr->leftPtr, token);
} else
if ((strCmpStr(token.content, rootPtr->content)) > 0) {
return BVSInsert_function(&rootPtr->rightPtr, token);
} else {
/* function is already present: return 0 */
return 0;
}
}
}
Note also that function strCpyStr may write beyond the end of the allocated area is len2 == s1->alloc, assuming s1->len is the length of the string, excluding the null terminator.
Here is a modified version:
int strCpyStr(string *s1, const string *s2) {
int len2 = s2->length;
if (len2 >= s1->alloc) {
char *newstr = (char *)realloc(s1->str, len2 + 1);
if (newstr == NULL) {
return 1;
}
s1->str = newstr;
s1->alloc = len2 + 1;
}
strcpy(s1->str, s2->str);
s1->length = len2;
return 0;
}

Heap buffer overflow on a getline() - C

I am coding a local server, I need to parse a file to get the config of the server.
Problem : I have a heap buffer overflow indicated at on the while.
This probeme is shown when I run with -fsanitize but I don't have any trouble without.
Here is the code :
struct container *configParse(FILE *file)
{
char *line = NULL;
size_t n;
char *token = NULL;
char *saveptr = NULL;
struct container *head = NULL;
struct container *container = NULL;
int key = 0;
int first = 1;
while ((getline(&line, &n, file)) != -1)
{
token = strtok_r(saveptr, " =\n\r", &line);
while (token != NULL)
{
if (token[0] == '[')
{
if (first)
{
container = container_init();
container->title = token;
head = container;
first = 0;
}
else
{
container = container_add_back(container);
container = container->next;
container->item = NULL;
container->title = token;
}
key = 0;
}
else
{
if (key == 0)
{
if (container->item == NULL)
{
container->item = items_init();
container->item->key = token;
}
else
{
struct item *itemcpy = container->item;
while (itemcpy->next != NULL)
{
itemcpy = itemcpy->next;
}
itemcpy->next = items_init();
itemcpy->next->key = token;
}
key = 1;
}
else
{
struct item *itemcpy = container->item;
while (itemcpy->next != NULL)
{
itemcpy = itemcpy->next;
}
itemcpy->value = token;
key = 0;
}
}
token = strtok_r(NULL, " =\n\r", &line);
}
}
container_print(head);
printf("\n*****Parsing du .conf*****\n\n");
if (isvalid(head))
printf("Parsing OK\n");
else
{
printf("Parsing KO\n");
return NULL;
}
return head;
}
Thanks in advance.
As explained I try to run the program without -fsanitze, and everything was fine

Compare cJSON objects in the same code every time program is executed

I have a code which is always running in the background. compareContents() reads contents from a file periodically (based on an event) and stores it in a cSJON object. I have to compare current contents of the file (cJSON object) with the previous contents (again a cJSON object) everytime, but I am getting a memory leak. Please help.
cJSON * prev = NULL, *current = NULL;
bool compare = false;
bool compareJSON(cJSON *i,cJSON *j) /* referred from https://cjson.docsforge.com/master/api/cJSON_Compare/ */
{
if (i->type != j->type) {
return false;
}
if (i->type == cJSON_Number && (i->valueint != j->valueint)) {
return false;
}
if (i->type == cJSON_String && strcmp(i->valuestring,j->valuestring)){
return false;
}
if (i->type==cJSON_Array)
{
cJSON *ic = i->child, *jc = j->child;
while (ic && jc)
{
if (!compareJSON(ic, jc)) {
return false;
}
ic = ic->next, jc = jc->next;
}
if (ic || jc)
return false;
}
if (i->type == cJSON_Object)
{
cJSON *ic = i->child;
while (ic)
{
cJSON *jc = cJSON_GetObjectItem(j,ic->string);
if (!jc || !compareJSON(ic,jc)){
return false;
}
ic = ic->next;
}
// And again, for j == i.
cJSON *jc = j->child;
while (jc)
{
cJSON *ic=cJSON_GetObjectItem(i,jc->string);
if (!ic || !compareJSON(ic,jc)){
return false;
}
jc = jc->next;
}
}
return true;
}
bool compareContents(){
int fd = open("/tmp/abc.txt", O_RDONLY);
char* data = (char *)malloc(st.st_size + 1); //st.st_size obtained from fstat
int n = read(fd, data, st.st_size);
data[n] = '\0';
cJSON* root = cJSON_Parse(data);
if(prev == NULL){ //first time execution of program
prev = root;
}
else {
if(current){
prev = current;
}
}
current = cJSON_Duplicate(root,1);
if (prev && current)
{
compare = compareJSON(prev,current);
}
if (fd >= 0)
close(fd);
if (access("/tmp/abc.txt", F_OK) == 0 && remove("/tmp/abc.txt") != 0){
printf("Error deleting the file\n");
}
if (data)
free(data);
if (root)
cJSON_Delete(root);
return compare;
}
I am not sure, but this seems like dynamic copy?
current = cJSON_Duplicate(root,1);
That is you never free current and prev if it was not null. Maybe start from this point? Seems like memory leak.

Insert function for Ternary Search Tree - C

I am new to C and am trying to code up a data structure, primarily, a ternary search tree. I am working under the assumption (for now) that valid char inputs are being passed in. I am having some issues with my insert function. Note that I am also inserting the original string in the last TSTnode where the last character of str will also be held.
Here is what I have so far
struct TSTnode {
char* word; // NULL if no word ends here
char self;
struct TSTnode *left, *sub, *right;
};
int insert_tst(struct TSTnode** tree, const char* str) {
return _insert(tree, str, 0);
}
int _insert(struct TSTnode** tree, const char* str, int position) {
if((*tree) == NULL) {
*tree = new_tst_node(*(str+position));
position = position + 1;
if(*(str+position) == '\0') {
(*tree)->word = strcpy((*tree)->word,str);
return 1;
}
}
else if ((*tree)->self > *(str+position)) {
position = position + 1;
_insert( &((*tree)->left), str, position);
}
else if ((*tree)->self < *(str+position)) {
position = position + 1;
_insert( &((*tree)->right), str, position);
}
else {
position = position + 1;
_insert( &((*tree)->sub), str, position);
}
return 0;
}
struct TSTnode* new_tst_node(char self) {
struct TSTnode* newNode = (struct TSTnode*) malloc(sizeof(struct
TSTnode));
if (newNode == NULL) {
return NULL;
}
newNode->word = NULL;
newNode->self = self;
newNode->left = NULL;
newNode->right = NULL;
newNode->sub = NULL;
return newNode;
}
Here is how I am testing:
struct TSTnode* tree = NULL;
char* words[1] = {"hello"};
for (int i = 0; i < 1; i++) {
if (insert_tst(&tree, words[i]) == 0) {
//print some error
}
else { //success }
EDIT - My issue is that none of my conditional branches are being taken and the insert function simply goes straight to return 0.
Note: You confusingly use tree for both TSTnode* and TSTnode**. I'm going to use tree_ptr for the latter, and pretend that you did the same.
Your claim is false. The body of if((*tree_ptr) == NULL) is executed. You do have a number of problems, though.
You don't handle the case where *tree_ptr == NULL && *(str+position+1) != '\0'.
You don't correctly handle the case where *tree_ptr != NULL && *(str+position+1) == '\0'.
You always return 0 when *tree_ptr != NULL || str[1] != '\0'.
You never allocate word, but you deference it. The thing is, you shouldn't be storing the string again anyway!
You don't handle the case where str[0] == '\0' (empty string).
Fixed:
int insert_tst(struct TSTnode** tree_ptr, const char* str) {
if (!*str)
return 0; /* Zero-length strings are not supported. */
return insert_tst_helper(tree_ptr, str, 0);
}
int insert_tst_helper(struct TSTnode** tree_ptr, const char* str, int position) {
if (*tree_ptr == NULL) {
*tree_ptr = new_tst_node(*(str+position));
if (*tree_ptr == NULL)
return 0; /* Memory allocation error. */
}
if (*(str+position+1) == '\0') { /* If the next char is a NUL */
(*tree_ptr)->is_word = 1;
return 1;
}
else if ((*tree_ptr)->self > *(str+position)) {
position = position + 1;
return insert_tst_helper( &((*tree_ptr)->left), str, position);
}
else if ((*tree_ptr)->self < *(str+position)) {
position = position + 1;
return insert_tst_helper( &((*tree_ptr)->right), str, position);
}
else {
position = position + 1;
return insert_tst_helper( &((*tree_ptr)->sub), str, position);
}
}
Untested.
Let's clean this up, though.
*(str+position)simplifies tostr[position]
ch == '\0'simplifies toch == 0then to!ch
position = position + 1; return insert_tst_helper(..., str, position);simplifies to++position; return insert_tst_helper(..., str, position);then toreturn insert_tst_helper(..., str, position+1);then toreturn insert_tst_helper(..., str+1, 0);then toreturn insert_tst(..., str+1);
Why is recursion being used at all???
Fixed:
int insert_tst(struct TSTnode** tree_ptr, const char* str) {
if (!*str)
return 0; /* Zero-length strings are not supported. */
while (1) {
if (*tree_ptr == NULL) {
*tree_ptr = new_tst_node(*str);
if (*tree_ptr == NULL)
return 0; /* Memory allocation error. */
}
if (!*(str+1)) { /* If the next char is a NUL */
(*tree_ptr)->is_word = 1;
return 1;
}
int cmp = *str - (*tree_ptr)->self;
if (cmp < 0) { tree_ptr = &( (*tree_ptr)->left ); }
else if (cmp > 0) { tree_ptr = &( (*tree_ptr)->right ); }
else { tree_ptr = &( (*tree_ptr)->sub ); }
++str;
}
}
Untested.

Resources