My WCHAR* variable prints unicode chars in my C project - c

I made a small linked map for my C project.
And I'm using this map for cache my checks,
I'm putting current file path to map. If the same file path request again, it has to get value from the cache map.
struct StrBoolNode {
const WCHAR* key;
BOOL* value;
struct StrBoolNode* next;
};
struct StrBoolTable {
struct StrBoolNode* first;
};
BOOL* strBoolTable_get(struct StrBoolTable* table, const WCHAR* key) {
wprintf(L"TEST strBoolTable_get %s \n", key);
struct StrBoolNode* node = table->first;
while (node != NULL) {
wprintf(L"strBoolTable_get WHILE %s \n", node->key); <<< prints here broken
if (wcscmp(key, node->key) == 0) return node->value;
node = node->next;
}
return NULL;
}
void strBoolTable_push(struct StrBoolTable* table, const WCHAR* key, BOOL value) {
wprintf(L"TEST strBoolTable_push 1 %s \n", key); <<< prints here normal
struct StrBoolNode* tmp = (StrBoolNode*)malloc(sizeof(struct StrBoolNode));
tmp->key = cloneKey;
tmp->value = (BOOL*)malloc(sizeof(BOOL));
*(tmp->value) = value;
tmp->next = NULL;
wprintf(L"TEST strBoolTable_push 2 %s \n", tmp->key); <<< prints here normal
if (table->first == NULL) {
table->first = tmp;
wprintf(L"TEST strBoolTable_push 3 %s \n", table->first->key); <<< prints here normal
return;
}
struct StrBoolNode* node = table->first;
while (node->next != NULL) {
node = node->next;
}
node->next = tmp;
wprintf(L"TEST strBoolTable_push 4 %s \n", node->next->key); <<< prints here normal
}
struct StrBoolTable cacheMap = { NULL };
WCHAR szFileName[MAX_PATH];
HMODULE hModule = NULL;
GetModuleHandleEx(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(LPCTSTR)retAddr,
&hModule);
GetModuleFileNameW(hModule, szFileName, 2048);
BOOL* cacheVal = strBoolTable_get(&cacheMap, szFileName);
if (cacheVal != NULL) return *cacheVal;
wprintf(L"Check => %s \n", szFileName); <<<< szFileName prints normal
strBoolTable_push(&cacheMap, szFileName, TRUE);
return TRUE;
There is no problem when pushing object to this map, but when I iterate and print the key in object, it returns unicode chars. Like this "Ï,♥".
Why does my object's key change to this later?
I marked where printed wrong print with <<<< in the code.

What is cloneKey that I see referenced in strBoolTable_push. It's note declared anywhere. How does that code compile?
My psychic powers suggest you are pushing a local array variable:
WCHAR szFileName[MAX_PATH];
Into your collection. But as soon as the function declaring szFileName returns, all bets are off (undefined behavior). The memory space is easily reclaimed and overwritten by anything that happens after the function returns. Your key is getting corrupted in the linked list when this happens.
Make sure you duplicate the string key before persisting it into your collection:
void strBoolTable_push(struct StrBoolTable* table, const WCHAR* key, BOOL value) {
wprintf(L"TEST strBoolTable_push 1 %s \n", key); <<< prints here normal
struct StrBoolNode* tmp = (StrBoolNode*)malloc(sizeof(struct StrBoolNode));
// wcsdup is equivalent to saying: tmp->key = malloc((wcslen(key)+1)*sizeof(WCHAR))); wcscpy(tmp->key, key);
tmp->key = _wcsdup(key);
Likewise, when you take a node out of list, make sure you free both the key and value members of each node.

Related

Function to insert node in linked list

I'm reading in words from a dictionary and then adding them to linked lists in a hash table. This works fine when I try inserting the nodes for each word within the while loop.
// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
FILE *dict = fopen(dictionary, "r");
if (dict == NULL)
{
return false;
}
// Set all next pointers to NULL in hash table
for (int i = 0; i < N; i++)
{
table[i] = NULL;
}
char word[LENGTH + 1];
while(fscanf(dict, "%s", word) != EOF)
{
// Get key from hash function
unsigned int key = hash(word);
node *pNode = getNode(word);
if (table[key] != NULL)
{
pNode->next = table[key];
}
table[key] = pNode;
words++;
}
fclose(dict);
return true;
}
I've tried refactoring this to a function insertNode with the exact same code but it doesn't work and the nodes seem to get lost and cause a memory leak. I assume it has something to do with how the arguments are passed into the function but as head is a pointer I would've thought it would work fine.
void insertNode(node *head, const char *key)
{
// Create node
node *pNode = getNode(key);
// Insert node into linked list
if (head != NULL)
{
// Make new node point to first item in linked list (a.k.a head)
pNode->next = head;
}
// Now point head to new node
head = pNode;
}
so the while loop within load would just call the function (which is defined before)
char word[LENGTH + 1];
while(fscanf(dict, "%s", word) != EOF)
{
// Get key from hash function
unsigned int key = hash(word);
// Add value to Hash table with head of linked list
insertNode(table[key], word);
words++;
}
As the 'head' variable is a pointer, you can just pass the value of 'head' by this pointer not the pointer itself, and in this case you try to override the local pointer inside the function.
Well look at this example to assign/change value to the pointer:
#include <stdio.h>
class A {
public:
int x;
};
// pass pointer by copy
void initialize(A* obj) {
obj = new A(); // obj not null here
obj->x = 2;
printf("x: %d\n", obj->x);
}
int main() {
A *a = nullptr;
initialize(a);
// a is still null here (pointer passed by copy)
printf("x: %d\n", a->x); // seg fault here, read on null
return 0;
}
The following code as you can see is incorrect. To fix this example you have to change the function prototype, and pass the pointer by pointer so it should lool like this:
#include <stdio.h>
class A {
public:
int x;
};
// pass pointer by pointer
void initialize(A** obj) {
*obj = new A(); // obj not null here
(*obj)->x = 2;
printf("x: %d\n", (*obj)->x);
}
int main() {
A *a = nullptr;
initialize(&a); // get the pointer address
// a is valid object here
printf("x: %d\n", a->x); // no error, x == 2
return 0;
}
So in your case it should be:
insertNode(&table[key], word);
and
void insertNode(node **head, const char *key)
{
// Create node
node *pNode = getNode(key);
// Insert node into linked list
if (*head != NULL)
{
// Make new node point to first item in linked list (a.k.a head)
pNode->next = *head;
}
// Now point head to new node
*head = pNode;
}

Int pointer is not null and can be printed but can not be passed into a function without throwing a segmentation fault

I am assigning an int pointer a value pulled from sscanf. I then want to pass it in to a method from a different file, counters_add. Although I can print out the value stored in the pointer and its address, as soon as I pass it to this method the program throws a seg fault. From testing I know that the program does not even get inside this method before seg faulting.
This method takes parameters of (counters_t *ctrs, const int key). The counters_t object is a struct I have defined earlier in the file.
I don't prematurely free anything and have verified that neither ctrs nor key are NULL. Why am I getting a segmentation fault?
int *key = malloc(sizeof(int));
//check if key is null here
sscanf(line, "%i", key);
printf("key: %i\n", *key); //this prints out the value
printf("key: %p\n", (void *)key); //this prints out the address
counters_add(ctrs, *key);//seg fault here, without even getting inside of method
Initialization of ctrs:
counters_t *ctrs = count_malloc(sizeof(counters_t));
if (ctrs == NULL) {
return NULL; // error allocating set
} else {
// initialize contents of set structure
ctrs->head = NULL;
}
The rest of the code:
void
counters_add(counters_t *ctrs, const int key)
{
if (key >= 0 && ctrs != NULL) {
// allocate a new node to be added to the list if the key is not already in the set
if(counters_get(ctrs,key) == 0) {//if it doesnt already exist
printf("after first if statement");
counternode_t *new = counternode_new(&key);//create it
printf("aftermaking new node");
new->next = ctrs->head;//add it to the head of the list
ctrs->head = new;
} else {
// increment the count
for(counternode_t *curr = ctrs->head; curr != NULL; curr = curr->next){
if (*(curr->key) == key){
*(curr->count) = *(curr->count) + 1;
}
}
}
}
}
int
counters_get(counters_t *ctrs, const int key)
{
printf("in counters_get");
if (ctrs == NULL) {
return 0; // null counter
} else if (ctrs->head == NULL) {
return 0; // set is empty
}//remove this in set
else {
for(counternode_t *curr = ctrs->head; curr != NULL; curr = curr->next)
{
if (*(curr->key) == key)
return *(curr->count);
printf("in loop");
}
return 0;
}
}
static counternode_t // not visible outside this file
*counternode_new(const int *key)
{
counternode_t *node = count_malloc(sizeof(counternode_t));
int *newkey = (int*)malloc(sizeof(int));
newkey = (int*) memcpy(newkey, key, (50 * sizeof(char)));
//make sure key is not over 50 ints
if (node == NULL || newkey == NULL) {
// error allocating memory for node or new key; return error
return NULL;
} else {
node->key = newkey;
*(node->count) = 1;
node->next = NULL;
return node;
}
}
Here is the counters struct:
typedef struct counters {
struct counternode *head; // head of the list of items in set
} counters_t;
here is the countersnode:
typedef struct counternode {
int *key;
int *count; //pointer to counter for this node
struct counternode *next; // link to next node
} counternode_t;
I see the problem in counternode_new:
static counternode_t // not visible outside this file
*counternode_new(const int *key)
{
counternode_t *node = count_malloc(sizeof(counternode_t));
int *newkey = (int*)malloc(sizeof(int));
newkey = (int*) memcpy(newkey, key, (50 * sizeof(char)));
...
}
In counters_add you pass to counternode_new a pointer to the variable d.
Then in counternode_new you want to copy in newkey 50 bytes with key as
the source. But key is pointer to a single integer, so you are reading 49
bytes out of bound, this leads to undefined behaviour which may lead to a
segfault. Also you are only allocating space for a single int for newkey. Besides, you are copying 50 bytes, not 50 integers. I don't get where the 50 comes from.
So your counternode_new call in counters_add makes no sense, first you have to
allocate space for a int[50] array and pass that to counternode_new.
I notice that newkey is having only sizeof(int) allocated, whereas you seem to copying 50 bytes to newkey.
int *newkey = (int*)malloc(sizeof(int));
newkey = (int*) memcpy(newkey, key, (50 * sizeof(char)));

elements storing

code print elements after store them :
void print(struct node* root)
{
while ( c != NULL )
{
printf( "\n%d ", c->line1);
printf( "%s", c->curr );
c = c->next;
}
}
print method
Just looking at the code, this line seems like a potential issue:
temp->curr=current_input;
It looks like all the nodes .curr will get set = current_input. I'm guessing you need to do something like:
temp->curr = malloc(1 + strlen(current_input));
strcpy(tmp->curr, current_input);
Use strcpy_s if strcpy causes a warning.
First you should realize a list consists of nodes, which contain pieces of your data — so you need to allocate a new node for each piece of data you want to store in a list.
Then you insert each newly created node into the list and finally print the list when done.
Additionaly remember that data need to be either copied into the node (like line1) or copied somewhere else, for example onto the heap, and then linked to the node with a pointer, like curr (see the answer by #rcgldr).
struct node *root = NULL;
struct node *createnode(int line, const char *input)
{
struct node *n = malloc(sizeof(struct node));
if(n != NULL)
{
n->line1 = line;
n->curr = input;
n->next = NULL;
}
return n;
}
void insertnode(struct node* n)
{
n->next = root;
root = n;
}
void printlist(struct node* n)
{
for( ; n != NULL; n = n->next)
{
printf( "%d: %s\n", n->line1, n->curr);
}
}
int main(int argc, const char * argv[])
{
char *input;
struct node *temp;
type t;
do
{
t=getword(); //call to get the type of t
switch (t)
{
case number:
case keyword:
input = strdup(current_input); // make a copy of user input
if(input != NULL)
{
temp = createnode(line, input);
if(temp != NULL) // created?
insertnode(temp); // insert into the list
else
{
free(input); // free unused input copy
t = EOF; // make the loop terminate
}
}
else // user input copy failed
t = EOF; // make the loop terminate
break;
default:
break;
}
}
while (t != EOF);
print(root);
return 0;
}

error with pointers and linked list node creation

I'm trying to read line input from a file, correctly parse the line, and add the three fields of information from the line onto a node in a linked list.
Here's my read from file function:
int readFile(char* file)
{
FILE *fp = fopen(file,"r");
char ch;
char line[50];
char string1[100];
char string2[100];
char string3[100];
char endLine[2];
int i = 0;
while(fscanf(fp, "%[^\t]\t%[^\t]\t%[^\n]", string1, string2, string3) == 3)
{
printf( "%s\t%s\t%s\n", string1, string2, string3);
addNode(string1, string2, string3, head, tail);
}
printNodes();
fclose(fp);
return 0;
}
And here is my addNode function:
// create stuff
Entry *entry = malloc(sizeof(Entry));
entry->name = string1;
entry->address = string2;
entry->number = string3;
Node* node = malloc(sizeof(Node));
node->entry = entry;
node->next = NULL;
// Empty list
if(head->next == NULL)
{
head->next = node;
}
// Else, add to the end of the list
else
{
Node* temp = head->next;
while(temp->next!= NULL)
{
temp = temp->next;
}
temp->next = node;
}
I get problems when I call printNodes, and only the last read node's information is printed X times, where X is the number of unique nodes I'm supposed to have. I think I'm having a problem where I'm overwriting an old node each time I create a new node, but I'm not entirely sure, as this is my first time with raw C code.
Thanks again!
EDIT:
here's the printNodes() function:
int printNodes(Node* head)
{
Node *temp = head->next;
while(temp->next != NULL)
{
printf("\n%s\t%s\t%s\n", temp->entry->name, temp->entry->address, temp->entry->number);
temp = temp->next;
}
return 0;
}
Your problem is here:
entry->name = string1;
entry->address = string2;
entry->number = string3;
You are providing the same memory location to every node. Those strings contain the last value you read in when you call printNodes().

C: Comparing Strings

I am using the below code to add nodes to a double linked list and arrange them such that they are in alphabetical order according to their word. The nodes consist of char * word, struct NODES * prev, and struct NODES * next. I am running into an issue when, after reading file testing a, the list looks like NULL <- a <-> file <-> testing -> NULL that adding a node containing word = c it places c before a instead of between a and file. The function prints "Add: Placing c before list head c" and seems to be evaluating c < a. But even with that evaluation being incorrect I do not know how it is replacing a before doing any node manipulation at all. If anyone know what could cause this issue I'd appreciate the advice. P.S. incoming NODES * arg is always in the form of arg -> next == NULL; arg -> prev == NULL; arg -> word != NULL; but list can have all fields NULL if no nodes have been added yet, list -> prev should always be NULL at the time the function is called and when the function terminates.
int addToList(struct NODES * list, struct NODES * arg){
fprintf(stderr,"Add: Adding %s\n", arg->word);
if(list->word == NULL){
list->word = (char *)malloc(strlen(arg->word));
strcpy(list->word, arg->word);
list->next = NULL;
list->prev = NULL;
fprintf(stderr,"Add: Head %s\n", list->word);
return 2;
}
struct NODES * abc = list;
while(abc->word != NULL){
if(strcmp(abc->word, arg->word)<0){
fprintf(stderr, "abc %s < arg %s", abc->word, arg->word);
if (abc->next != NULL)
abc = abc->next;
else{
abc->next = malloc(sizeof(NODE));
abc->next->prev = abc;
abc = abc->next;
abc->next = NULL;
abc->word = NULL;
}
}
else if(abc == list){
fprintf(stderr, "Add: Placing %s before list head %s\n", arg->word, list->word);
arg->next = list;
list->prev = arg;
arg->prev = NULL;
list = arg;
fprintf(stderr, "Add: Placed %s before %s\n", list->word, list->next->word);
return 3;
}
else{
fprintf(stderr, "Add: Placing %s between %s and %s\n", arg->word, abc->word, abc->next->word);
arg->next = abc;
arg->prev = abc->prev;
if(abc->prev != NULL)
abc->prev->next = arg;
abc->prev = arg;
fprintf(stderr, "Added %s after %s and before %s\n", arg->word, arg->prev, arg->next->word);
return 1;
}
}
abc->word = (char *)malloc(strlen(arg->word));
strcpy(abc->word, arg->word);
fprintf(stderr, "Added %s after %s and before %s\n", abc->word, abc->prev->word, abc->next);
return 1;
}
Updated to reflect suggestions:
int addToList(struct NODES ** list, struct NODES * arg){
fprintf(stderr,"Add: Adding %s current head %s\n", arg -> word, (*list)->word);
if((*list) -> word == NULL){
(*list) -> word = malloc(strlen(arg->word)+1);
strcpy((*list) -> word, arg -> word);
(*list) -> next = NULL;
(*list) -> prev = NULL;
fprintf(stderr,"Add: Head %s\n", (*list) -> word);
return 2;
}
struct NODES * abc = (*list);
//while arg > abc
fprintf(stderr,"Comparing %s and %s\n", abc->word,arg->word);
while(strcmp(abc->word, arg->word)<0){
fprintf(stderr,"Comparing %s and %s\n", abc->word,arg->word);
if (abc -> next == NULL)
break;
abc = abc -> next;
}
if (abc == (*list)){
if(!(strcmp(abc->word, arg->word)<0)){
arg -> next = abc;
arg -> prev = NULL;
abc -> prev = arg;
*list = arg;
}
else{
abc -> next = arg;
arg -> prev = abc;
abc -> next = NULL;
}
return 5;
}
if(abc -> next != NULL){
fprintf(stderr, "Inserting %s between %s and %s\n", arg -> word, abc->prev->word,abc->word);
arg -> next = abc;
arg -> prev = abc -> prev;
arg -> prev -> next = arg;
abc -> prev = arg;
fprintf(stderr, "Added %s before %s and after %s\n", arg->word, arg->prev->word,arg->next->word);
return 3;
}
return 0
}
The list argument received by the function is a copy of the list pointer the caller has. To return a revised list pointer the function could be like this:
int addToList(struct NODES ** list, struct NODES * arg)
and it would be called something like this:
result = addToList(&list, arg);
The function would provide a new list pointer like this
*list = arg;
and all the list access you currently have would be one step more indirect
if(list->word == NULL)
would become
if((*list)->word == NULL)
UPDATE
Try this simplified code, I found this easier than getting my head round yours.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct NODES {
struct NODES *prev;
struct NODES *next;
char *word;
};
void showList(struct NODES * list) {
while (list) {
if (list->prev)
printf("%-10s", list->prev->word);
else
printf("%-10s", "NULL");
printf(" <- %-10s -> ", list->word);
if (list->next)
printf("%-10s", list->next->word);
else
printf("%-10s", "NULL");
printf("\n");
list = list->next;
}
}
int addToList(struct NODES ** list, char *word){
struct NODES *wptr, *lptr = *list, *pptr = NULL;
if ((wptr = malloc(sizeof(struct NODES))) == NULL)
return -1;
wptr->prev = NULL;
wptr->next = NULL;
if ((wptr->word = strdup(word)) == NULL)
return -2;
if (lptr == NULL) {
*list = wptr; // first list item
return 0;
}
while (lptr) {
if (strcmp(word, lptr->word) <= 0) {
wptr->next = lptr; // insert before current node
wptr->prev = pptr;
if (pptr)
pptr->next = wptr;
else
*list = wptr;
lptr->prev = wptr;
return 1;
}
pptr = lptr;
lptr = lptr->next;
}
wptr->prev = pptr; // insert at tail
pptr->next = wptr;
return 2;
}
int main()
{
struct NODES *list = NULL;
addToList(&list, "one");
addToList(&list, "two");
addToList(&list, "three");
addToList(&list, "four");
addToList(&list, "five");
showList(list);
return 0;
}
Program output:
NULL <- five -> four
five <- four -> one
four <- one -> three
one <- three -> two
three <- two -> NULL
I suspect your problem is here:
list->word = (char *)malloc(strlen(arg->word));
strcpy(list->word, arg->word);
Since you do not allocate room for the terminating null-character, later calls to strcmp will read beyond the allocated buffer. This can have all sorts of behaviours, most likely also the one you see.
Also, drop the (char *) cast, it may hide other problems with your code.

Resources