Unexpect behaviour with pointer array - c

im currently implementing a basic linked list structure on C.
Basically im parsing a txt file, and I buffer each line into a Node which contains a pointer to an array of integers. The problem is, that my data (the array of integers) doesn't save correctly / i don't know how to iterate through it correctly.
These are the structures that I use:
typedef struct Node
{
struct Node* next;
struct Node* prev;
int* data;
int len;
} Node;
typedef struct LinkedList
{
Node* head;
Node* tail;
} LinkedList;
and I use this method to create a new node from a buffered string:
int nodeManager(FILE* filePointer, char* buffer, char* token, LinkedList* linkedList)
{
token = strtok(buffer, DELIMITER);
int* data = (int*)malloc(sizeof(int));
int dataIndex = 0;
if (data == NULL)
{
fprintf(stderr, DATA_ALLOCATION_ERROR);
freeLinkedList(linkedList);
fclose(filePointer);
return EXIT_FAILURE;
}
const char* insertPosition = token;
while ((token = strtok(NULL, DELIMITER)))
{
data = realloc(data, dataIndex + 1);
if (data == NULL) {
fprintf(stderr, DATA_ALLOCATION_ERROR);
freeLinkedList(linkedList);
fclose(filePointer);
return EXIT_FAILURE;
}
char *res;
int num = (int) strtol(token, &res, 10);
data[dataIndex] = num;
dataIndex++;
}
Node* newNode = (Node*)malloc(sizeof(Node));
if (newNode == NULL)
{
freeLinkedList(linkedList);
free(data);
fclose(filePointer);
return EXIT_FAILURE;
}
newNode -> prev = NULL; newNode -> next = NULL;
newNode -> len = dataIndex; newNode -> data = data;
if(strcmp(insertPosition, INSERT_TO_START) == 0)
{
addToStartLinkedList(linkedList, newNode);
}
else
{
addToEndLinkedList(linkedList, newNode);
}
return EXIT_SUCCESS; // TODO - Change
}
A line of input looks like this:
start,1,2,3,4,5,6,7,10,22,44,55,66,66,77
for some reason, node -> data doesn't get all the values that I assign in this method and I can't really tell why.
I tried to print the values like this:
for (int i = 0; i < newNode -> len; i++)
{
printf("%d,", (newNode -> data)[i]);
}
However, as I said, something quite doesn't work with my assigment, or I just don't know how to access the values correctly.
Would love to get some insight - thanks.

This part is wrong:
data = realloc(data, dataIndex + 1);
You have forgotten to multiply with sizeof(int) or better sizeof *p
BTW: Be careful about doing realloc directly into data. On failure realloc may return NULL and then you have a memory leak. You should use a temporary pointer like:
int * temp = realloc(data, SOME_SIZE);
if (temp == NULL)
{
// oh dear, add error handling here - maybe a return or whatever fits
}
else
{
// All good
data = temp;
}
OT: Passing the file pointer to the function in order to be able to close the file is (IMO) a rather strange design. Instead, the caller should check the return value and close the file (if desired).

Related

print from users input linked list of struct

I am required to have a list of structs of sentence nodes that point to a struct of word nodes. I am trying to print the user's input.
I have a program that runs properly when I manually give it the input (see test section of the code). It does not, however, work when I use my input1() function.
I've tried debugging it, but I can't seem to find the problem.
I removed all printf lines that I used to debug. I also removed all the irrelevant code.
I am looking to know how to fix it and what is wrong so I can run it with no problems.
What I learned from debugging it is that (only when using input1() and not in the test) the head is overwritten every time and all the nodes as well.
I also tried using a double pointer instead of returning para but that didn't help.
any help will be appreciated,
thanks in advance
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
typedef struct word
{
char * ch;//poiter to char
}
W;
typedef struct sentence
{
W * currentWord;//pointer to a word
int lineNumber;// holds the line number
int numbersOfWords;//holds the number of words
struct sentence* link;
}
sent;
typedef struct list
{
sent* head;
int count;
}
LISTS;
LISTS* createList()
{
LISTS* list;
list= (LISTS*) malloc (sizeof (LISTS));
if (list)
{
list-> head = NULL;
list-> count = 0;
}
return list;
} // createList
void printList(LISTS* list)
{
sent *temp = list -> head;
//iterate the entire linked list and print the data
while(temp != NULL)
{
printf("%s\n", temp->currentWord->ch);
temp = temp->link;
}
// printf("NULL\n");
}
void insertSentList (LISTS* list, W* itemPtr)
{
sent* newPtr; //new node
if (!(newPtr = (sent * ) malloc(sizeof(sent)))){
printf(" Memory can not be allocated.");
return;
}
newPtr->currentWord = itemPtr;
newPtr->link = NULL;
if(list->head == NULL)
{
list->head = newPtr;
}else{
sent* current = list->head;
while(current->link != NULL){
current = current->link;
}
current -> link = newPtr;
}
(list->count)++;
return;
} // insertList
LISTS * input1(LISTS *para)
{
char * line;
line = (char * ) malloc(1000 * sizeof(char));
line[0] = '\0';
while (line[0] != '\n')
{
W word;
word.ch = (char * ) malloc(100);
printf(" Please input a line : ");
fgets(line, 1000, stdin);
if(line[0] != '\n'){
strcpy(word.ch, line);
insertSentList(para,&word);
}
}
free(line);
return para;
}
int main()
{
///////////////////test////////////////
LISTS* list = createList();
W word;
word.ch= "word0 ";
W word1;
word1.ch= "word1 ";
W word2;
word2.ch= "word2";
insertSentList(list,&word);
insertSentList(list,&word1);
insertSentList(list,&word2);
insertSentList(list,&word);
insertSentList(list,&word1);
insertSentList(list,&word2);
printList(list);
///////////////////test////////////////
LISTS *para = createList();
para= input1(para);
printList(para);
return 0;
}
Main problem with the posted code is that "ownership" of the sent and W objects in a list is not well defined. For example word.ch= "word0 "; in main sets the ch pointer pointing to a string literal (which it does not own), but word.ch = malloc(100); in input1 points it to dynamically allocated memory (which it should own, and remember to free later). Because of this, memory allocations cannot be tracked reliably and, even in the cases where things appear to "work", there are multiple memory leaks. It also breaks when the inserted objects are local variables that do not live for the entire lifetime of the list object.
The simplest (if not necessarily the best or most efficient) solution would be to dynamically allocate all objects that go into the list, make the list own them all, and add a function to cleanup once done. To that end insertSentList could be modified as follows.
void insertSentList (LISTS* list, W* itemPtr)
{
sent* newPtr; //new node
if (!(newPtr = malloc(sizeof(sent)))){
printf(" Memory can not be allocated.\n");
return;
}
W *newItem = malloc(sizeof(W)); // <-- make a deep copy of the `itemPtr` argument
newItem->ch = strdup(itemPtr->ch); // including a copy of the string itself
newPtr->currentWord = newItem; // <-- save the copy in the list, not the argument
newPtr->link = NULL;
if(list->head == NULL)
{
list->head = newPtr;
}else{
sent* current = list->head;
while(current->link != NULL){
current = current->link;
}
current->link = newPtr;
}
list->count++;
} // insertList
For proper cleanup and to avoid memory leaks, the following freeList should be called for each list pointer returned by createList and filled by insertSentList.
void freeList(LISTS *list)
{
sent *temp = list->head;
while(temp != NULL)
{
sent *next = temp->link;
free(temp->currentWord->ch);
free(temp->currentWord);
free(temp);
temp = next;
}
free(list);
}

Why do I get a segmentation fault printing the contents of my linked list?

I am trying to implement a stack-esque structure using a linked list in C. Eventually it will read strings of varying length from an input file, thus the need for dynamic memory. I am getting a segmentation fault at the printf in printList and I cannot figure out why. I was also getting segmentation faults in push earlier, but I seem to have fixed them. In case it's not obvious, my intent is to add elements only to the "top" of the list.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void* emalloc(size_t n);
typedef struct node {
struct node* next;
char* word;
} node;
node* head = NULL;
void* emalloc(size_t n) {
void* p;
p = malloc(n);
if(p == NULL) {
fprintf(stderr, "Failed to allocate memory.");
exit(1);
}
return p;
}
void push(char* w) {
if(head == NULL) {
head = (node*) emalloc(sizeof(node));
head->word = (char*) emalloc(strlen(w) * sizeof(char) + 1);
strncpy(head->word, w, strlen(w) + 1);
printf("Pushed a word to head.");
return;
}
node* newnode = (node*) emalloc(sizeof(node));
newnode->word = (char*) emalloc(strlen(w) * sizeof(char) + 1);
strncpy(newnode->word, w, strlen(w) + 1);
newnode->next = head;
head = newnode;
}
void printList() {
node* cur = head;
if(cur == NULL || cur->word == NULL) printf("Whoops!");
while(cur != NULL) {
printf(cur->word);
cur = cur->next;
}
}
/*
* The encode() function may remain unchanged for A#4.
*/
void main() {
char word[20] = "Hello world";
//push("Hello",head);
//push("World",head);
//push("!",head);
push(word);
printList();
}
Why copy to 1 past end of string in push()? Also, if string is too long, strncpy won't NUL it for you.
The real crash though is in the "Head" creation, the first if statement when no entries exist. It does not NULL its next pointer so therefore list traversal will will blow up on last entry as it reads a garbage pointer at the end of the list.
it worked for me, as michael Dorgan ask why did you 1 byte past the end of the string.
I recomend to use something like :
int len =strlen(w)
before
node* newnode = (node*) emalloc(sizeof(node));
newnode->word = (char*) emalloc(len * sizeof(char));
strncpy(newnode->word, w, len)[len]=0;
newnode->next = head;
this temporal variable eliminate the need of use strlen on these locations.

How to store values with same memory location in c?

If I have a file stream with content
123 1234
1223 124235
21432 325
In my program I read line by line of the file and store the first target of each line into my list. These line with same location and when I run the program it will keep pointing to the most recent data and place it in to list. Which means If I have a function called printL() in while loop. It will print
123/
1223/1223/
21432/21432/21432/
instead of
123/
123/1223/
123/1223/21432
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct n{
char *value;
struct n *next;
} Node;
void printList(Node *head){
Node *cur = head;
while(cur!=NULL){
printf("%s/", cur->value);
cur = cur->next;
}
printf("\n");
}
void insertIntoList(Node **head, char *data){
Node *newNode = malloc(sizeof(Node));
if (newNode == NULL){
perror("Failed to allocate a new node for the linked list");
exit(1);
}
newNode->value = data;
newNode->next = NULL;
Node *currentList = *head;
if(*head == NULL){ //if the linked list head is null, then add the target into linked list
*head = newNode;
}
else{
while(currentList->next!=NULL){
currentList = currentList->next;
}
currentList->next = newNode;
}
}
int main(int argc, char**argv){
FILE *fileStream;
size_t len = 0;
char *line = NULL;
Node *head = NULL;
int j;
for(j=1; j<argc-2;j++){
fileStream = fopen(argv[j], "r");
if(fileStream == NULL){
fprintf(stderr, "could not open");
continue;
}
insertIntoList(&head,"a"); /////////////Line 95
insertIntoList(&head,"b");
insertIntoList(&head,"c");
insertIntoList(&head,"d");
printf("here is a try\n");
printList(head);
while(getline(&line, &len, fileStream)!=EOF){ /////////////Line 101
char *targetNum = strtok(line, " \t\r\n");
printf("*****%s\n", targetNum);
insertIntoList(&head, targetNum);
printf("######print head here is##########\n");
printList(head);
printf("######print head here is##########->\n");
}
//printList(head);
}
return 0;
}
In order to keep the content of each loaded field returned from strtok(), just add a strdup() before calling insertIntoList() after checking if not a null-pointer.
In your code, if you compare the value of both line and targetNum
are the same. If fact, the strtok() function returns a pointer to
the input string and keep the pointer for the next argument.
Replace the following code:
char *targetNum = strtok(line, " \t\r\n");
printf("*****%s\n", targetNum);
insertIntoList(&head, targetNum);
By that one:
char *targetNum = strtok(line, " \t\r\n");
if (targetNum != NULL) {
printf("*****%s\n", targetNum);
insertIntoList(&head, strdup(targetNum));
}
You don't store the contents of the string in your list nodes; you store a pointer to the buffer used for the contents of the string.
Consider changing your list node structure to
typedef struct node Node;
struct node {
Node *next;
char data[];
};
where the contents of the string are stored in the C99 flexible array member.
Your node constructor is then something like
Node *new_node(const char *data)
{
const size_t datalen = (data) ? strlen(data) : 0;
Node *result;
result = malloc(sizeof (Node) + datalen + 1);
if (!result) {
fprintf(stderr, "Out of memory!\n");
exit(EXIT_FAILURE);
}
if (datalen > 0)
memcpy(result->data, data, datalen);
result->next = NULL;
result->data[datalen] = '\0';
return result;
}
See how the function allocates memory for the copy of the data?
Personally, I prefer something like
typedef struct node Node;
struct node {
Node *next;
size_t hash;
size_t size;
char data[];
};
where the size member is basically strlen(data) (except that you can also use the nodes to hold binary data that includes nul bytes \0), and hash is a simple hash computed from data. hash is useful if you intend to compare the entire contents of nodes; if two nodes' lengths or hashes differ, then it is certain their contents differ; if they are the same, then you compare them character by character (memcmp(node1->data, node2->data, node1->length) == 0 if they are the same).
The constructor for the above is something like (using DJB2 hash):
Node *new_node(Node *next, const void *data, const size_t size)
{
Node *result;
result = malloc(sizeof (Node) + size + 1);
if (!result) {
fprintf(stderr, "new_node(): Out of memory (%zu bytes)\n", size);
exit(EXIT_FAILURE);
}
/* Copy and hash data using DJB2 hash (not that good, but fast) */
{
unsigned char *src = (unsigned char *)data;
unsigned char *const end = (unsigned char *)data + size;
unsigned char *dst = result->data;
size_t hash = 5381;
while (src < end) {
hash = hash * 33 + (size_t)(*src);
*(dst++) = *(src++);
}
/* Add terminator */
*dst = '\0';
}
result->next = next;
result->hash = hash;
result->size = size;
return result;
}
These Nodes can also be used in e.g. hash tables, which makes the type quite versatile.

freeing allocated memory generates segmentation fault

I tried reading from text file, and then put every word in list node(and print it afterwards in reverse order).
The program works good, but when trying to free the allocated list nodes, the program crash.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
#include <math.h>
typedef struct node{
char* word;
struct node* next;
}; typedef struct node* list;
void freeall(list lst){
list temp = NULL;
while (lst)
{
temp = lst->next;
free(lst);
lst = temp;
}
#if 0
if (lst == NULL){ return; }
freeall(lst->next);
free(lst->word);
free(lst);
#endif // 0
}
void deleteAllNodes(list start)
{
while (start != NULL)
{
list temp = start;
free(temp);
start = start->next;
}
}
list createNode(char* buff){
list newnode = (list)malloc(sizeof(list));
assert(newnode);
newnode->next = NULL;
newnode->word = (char*)calloc(strlen(buff), sizeof(char));
assert(newnode->word);
strcpy(newnode->word, buff);
return newnode;
}
void reverse(const char *str) //you don't need to modify your string
{
if (*str != '\0'){ //if the first character is not '\O'
reverse((str + 1)); // call again the function but with +1 in the pointer addr
printf("%c", *str); // then print the character
}
}
void print_reverse(list lst){
if (lst == NULL) return;
print_reverse(lst->next);
reverse(lst->word);
//free(lst->word);
}
list createList(FILE* ifp){
struct node *loop = NULL;
list curr = NULL;
list lst = NULL;
char *word = NULL;
size_t size = 2;
long fpos = 0;
char format[32];
if (ifp == NULL) // open file
perror("Failed to open file \n");
if ((word = malloc(size)) == NULL) // word memory
perror("Failed to allocate memory");
sprintf(format, "%%%us", (unsigned)size - 1); // format for fscanf
while (fscanf(ifp, format, word) == 1) {
while (strlen(word) >= size - 1) { // is buffer full?
size *= 2; // double buff size
printf("** doubling to %u **\n", (unsigned)size);
if ((word = realloc(word, size)) == NULL)
perror("Failed to reallocate memory");
sprintf(format, "%%%us", (unsigned)size - 1);// new format spec
fseek(ifp, fpos, SEEK_SET); // re-read the line
if (fscanf(ifp, format, word) == 0)
perror("Failed to re-read file");
}
curr = createNode(word);
if (lst == NULL){lst = curr;}
else{
loop = lst;
while (loop->next != NULL) {//loop to last structure
loop = loop->next;//add structure to end
}
loop->next = curr;
}
fpos = ftell(ifp); // mark file pos
}
free(word);
return lst;
}
int main(int argc, char* argv[]){
assert(argc == 2);
FILE *ifp = fopen(argv[1], "r");
assert(ifp);
list lst = NULL;
lst = (list)malloc(sizeof(list));
lst = createList(ifp);
print_reverse(lst);
fclose(ifp);
//freeall(lst);
//deleteAllNodes(lst);
return 1;
}
your delete all nodes has a bug in it. You freed a pointer and tried accessing it immediately. So the program crashes You can try this
void deleteAllNodes(list head)
{
list ptr = head;
while ((ptr = head) != NULL)
{
head = head->next;
free (ptr);
}
}
point the current ptr to the head and point head to next element. Delete the current pointer.
In your deleteAllNodes function you are free-ing a pointer and then accessing it. You could try deleting nodes in reverse order, starting from the last one, for instance with a recursive function.
void deleteAllNodes(list start)
{
if (start != NULL)
{
deleteAllNodes(start->next);
free(start);
}
}
Or you can stick to the iterative forward deletion with something like (untested):
void deleteAllNodes(list start)
{
list previous = NULL;
while (start != NULL)
{
if (previous != NULL)
free(previous);
previous = start;
start = start->next;
}
if (previous != NULL)
free(previous);
}
The problem , as I see it is with
list newnode = (list)malloc(sizeof(list));
your list is a typedef to struct node*, so this statement is essentially
list newnode = (list)malloc(sizeof(struct node*));
which is wrong. You're allocating memory for a pointer to structure variable, whereas, you should be allocating memory equal to the size of the structure variable itself.
Two things to mention here
Please see why not to cast the return value of malloc() and family in C.
Never use a typedef for a pointer type. It's not a "rule", but better to stick to it.
Your allocation statement, at least, shall look like
list = malloc(sizeof*list);
Apart from this, in your main() function,
First, you're allocating memory to lst using malloc() [Same issue with the allocation as above]
Then, you assign another pointer, the return value of createList() to lst.
This way, you're overwriting the allocated mekory through malloc(), creating memory leak. You don't need malloc() there, at all.

Error in Display the linked list

Folks,
I don't know whether I am asking silly question. But tried to figure out my problem, but fail to that.
my structure is
typedef struct {
uint16 nwkaddr;
uint8 extaddr[8];
}device_t;
typedef struct node{
device_t list;
struct node *link;
}address_list;
The Data coming from UART is
1010,23CD1234,CD32454F,12F439AF,! . This I need to parse and store the mac list.
while(data[j] != '!')
{
if(data[i] == ',')
{
i = i+1;
memset(addr, 0, 9);
memcpy(addr, &data[i], 8);
// addr[8] = '\0';
if(addr != 0)
{
insert_MacList(addr);
}
}
i = i+8;
j = i+1;
}
the Created list is
void insert_MacList(uint8 *mac)
{
address_list *curr, *temp;
//curr = (address_list*)malloc(sizeof(address_list));
curr = osal_mem_alloc(sizeof(address_list));
strcpy((char*)curr->list.extaddr, (char const*)mac);
temp = head;
if(head == NULL)
{
head = curr;
head->link = NULL;
}
else
{
while(temp->link !=NULL)
{
temp = temp->link;
}
curr->link = NULL;
temp->link = curr;
}
}
I am trying to print all address,But I am fail to get 23CD1234. But after that I am getting correctly.
void check_inlist(void)
{
address_list *temp;
temp = head;
while(temp != NULL)
{
/*print data and send to UART*/
temp = temp->link;
}
}
Why head is changing to second element, is 23 value creating some problem?. So can some help me
You are using strcpy to copy data that isn't null terminated!
You can change it like this:
strncpy((char*)curr->list.extaddr, (char const*)mac, sizeof curr->list.extaddr); // strncpy won't write past the end of the array
You have
typedef struct {
uint16 nwkaddr;
uint8 extaddr[8];
}device_t;
But in insert_MacList() you call
strcpy((char*)curr->list.extaddr, (char const*)mac);
what copies 9 bytes (8 values + terminating '\0'). That might cause the problem.

Resources