Calling this value works for the first 2 calls and then causes a segmentation fault.
void insert_message(char *id, char *message) {
if (first_message == NULL) {
first_message = malloc( sizeof(struct server_message) );
strcpy(first_message->id, id);
strcpy(first_message->message, message);
first_message->next_msg = NULL;
} else {
struct server_message *curr_msg = first_message;
while (curr_msg != NULL) {
curr_msg = curr_msg->next_msg;
}
curr_msg->next_msg = malloc( sizeof(struct server_message) );
strcpy (curr_msg->next_msg->id, id);
strcpy (curr_msg->next_msg->message, message);
curr_msg->next_msg->next_msg = NULL;
}
}
First Message and Server Message struct:
// used to store messages.
struct server_message {
char message[80];
char id[80];
struct server_message *next_msg;
};
//head of the list
static struct server_message *first_message = NULL;
Your loop finishes when curr_msg == NULL holds. Calling curr_msg->next_msg = malloc( sizeof(struct server_message) ); will fail since you cannot dereference NULL. Hence do the following:
while (curr_msg->next_msg != NULL) {
curr_msg = curr_msg->next_msg;
}
// curr_msg is now the last node in your list
As per your loop , after came out of loop , you have to allocate memory for curr_msg & you have to fill the necessary info in that curr_msg structure. Because in your curr_msg structure ,already you stored the link to next_msg
so you have to modify your code like below
while (curr_msg != NULL)
{
curr_msg = curr_msg->next_msg;
}
curr_msg = malloc( sizeof(struct server_message) );
strcpy (curr_msg->id, id);
strcpy (curr_msg->message, message);
curr_msg->next_msg = NULL;
Related
Firstly I'm using C language. I want a variable that I refer to as a parameter to change outside the function when it is changed inside the function. But the problem is that the variable is of type linked list and I want to add to the linked list.
So what I'm trying to do is add the linked list outside the function with the save function.
Is this possible? If possible how can I do it? Sorry for the English, I used a translator.
My codes:
#include <stdio.h>
#include <stdlib.h>
typedef struct NS
{
char * name;
char * value;
struct NS * next;
} n_t;
void save(char * name, char * value, n_t ** item)
{
n_t * link = malloc(sizeof(struct NS));
link->name = name;
link->value = value;
link->next = NULL;
n_t ** pointer = NULL;
if (*item == NULL)
*item = link;
pointer = &(*item);
while ((*pointer)->next != NULL)
*pointer = (*pointer)->next;
(*pointer)->next = link;
}
int main()
{
n_t * mem = NULL;
save("hello", "val123", &mem);
printf("-> %s\n", mem->value);
save("abc", "hello", &mem);
printf("-> %s\n", mem->value);
printf("-> %s\n", mem->next->value);
return 0;
}
The output for the first arrow (->) should be "val123"
The result that should also appear in the second arrow output is "val123"
The result that should appear in the third arrow output is "hello"
All this part of the function
n_t ** pointer = NULL;
if (*item == NULL)
*item = link;
pointer = &(*item);
while ((*pointer)->next != NULL)
*pointer = (*pointer)->next;
(*pointer)->next = link;
does not make sense. For example in the while loop
while ((*pointer)->next != NULL)
*pointer = (*pointer)->next;
there is rewritten the value of the passed original pointer to the function by reference,
The function can look the following way
int save( n_t **item, char *name, char *value )
{
n_t * link = malloc( sizeof( struct NS ) );
int success = link != NULL;
if ( success )
{
link->name = name;
link->value = value;
link->next = NULL;
while ( *item != NULL ) item = &( *item )->next;
*item = link;
}
return success;
}
In general you need to dynamically allocated memory to store copies of the strings name and value in the nodes of the list.
The body of the function main can look like
n_t * mem = NULL;
save( &mem, "hello", "val123" );
printf("-> %s\n", mem->value);
save( &mem, "abc", "hello" );
printf("-> %s\n", mem->next->value );
printf("-> %s\n", mem->next->next->value);
You're really only missing a single return when the list is empty still:
if (*item == NULL) {
*item = link;
return;
}
#define UNIT_ARRAY_SIZE 1024
struct UserInfo {
char *name;
char *id;
int purchase;
};
struct DB {
struct UserInfo *pArray;
int curArrSize;
int numItems;
};
DB_T CreateCustomerDB(void) {
DB_T d;
d = (DB_T) calloc(1, sizeof(struct DB));
if (d == NULL) {
fprintf(stderr, "Can't allocate a memory for DB_T\n");
return NULL;
}
d->curArrSize = UNIT_ARRAY_SIZE; // start with 1024 elements
d->pArray = (struct UserInfo *)calloc(d->curArrSize,
sizeof(struct UserInfo));
if (d->pArray == NULL) {
fprintf(stderr, "Can't allocate a memory for array of size %d\n",
d->curArrSize);
free(d);
return NULL;
}
return d;
}
void
DestroyCustomerDB(DB_T d)
{
if (d == NULL) return;
struct UserInfo *p;
struct UserInfo *nextp;
for (p = d->pArray; p != NULL; p = nextp) {
nextp = p + 1;
free(p->id);
free(p->name);
}
free(d->pArray);
free(d);
}
when i test the DestoryCustomerDB it makes segmentation fault,
I think it is because, Although I allocated the memory to d->pArray with calloc, size d->curArrsize,
for loop in DestoryCustomerDB iterates forever. why this happen?
and am i doing freeing correctly? Thank you,
for (p = d->pArray; p != NULL; p = nextp) { can fail as there is no certain p == NULL.
Iterate to curArrSize instead.
while (d->curArrSize > 0) {
struct UserInfo *p = d->pArray[--(d->curArrSize)];
free(p->id);
free(p->name);
}
I am currently working on a piece of code where we are parsing a file and working with different functions. Through debugging with printf calls, I have found that I am getting a memory error on the second malloc call. What could cause the second malloc to fail in this rough skeleton?
struct example {
char *myChar;
int myInt;
};
struct example *doThing(FILE *file) {
struct example *myToken = (struct example *)malloc(sizeof(struct example));
char buffer[32] = "";
// other stuff
if (strncmp(buffer, "random", 6) == 0) {
strncpy(myToken->myChar, buffer, 6);
myToken->tokenid = 1;
return myToken;
}
return NULL;
}
struct example *doThing2(FILE *file) {
struct example *myOtherToken = (struct example *)malloc(sizeof(struct example));
// other stuff
return myOtherToken;
}
int main() {
FILE *ofp = fopen("thefile.txt", "r");
struct example *token1, *token2;
token1 = doThing(ofp);
token2 = doThing2(ofp);
// other stuff
free(token1);
free(token2);
return 0;
}
You are facing memory leak.
correct your code folowing one of the two samples bellow
and yes, as #Eugene_Sh mentioned, you should allocate memory for myToken->myChar and do not forget to free it before freeing myToken
SAMPLE 1
struct example* doThing(FILE *file) {
char buffer[32] = "";
// other stuff
if (strncmp(buffer, "random", 6) == 0) {
struct example *myToken = (struct example *) malloc(sizeof(struct example));
myToken ->myChar= malloc(7);
strncpy(myToken ->myChar, buffer, 6);
myToken ->myChar[6]=0;
myToken->tokenid = 1;
return myToken;
}
return NULL;
}
SAMPLE 2
struct example* doThing(FILE *file) {
struct example *myToken = (struct example *) malloc(sizeof(struct example));
char buffer[32] = "";
// other stuff
if (strncmp(buffer, "random", 6) == 0) {
myToken ->myChar= malloc(7);
strncpy(myToken ->myChar, buffer, 6);
myToken ->myChar[6]=0;
myToken->tokenid = 1;
return myToken;
}
free(myToken );
return NULL;
}
I have Node and Queue structs in the file queue.h
#ifndef QUEUE_H
#define QUEUE_H
#include<stdio.h>
#include<stdbool.h>
typedef struct rcb
{
int seq_no;
int file_desc;
FILE *fp;
long sent;
long sizeOfFile;
char *request_http_method;
char *request_file;
char *request_http_version;
int level;
bool is_new_created;
int remaining;
}* RCB;
/*
* Node of the queue.
*/
typedef struct node {
RCB info; //Data of each node.
struct node *ptr;//pointer to the next node.
} * Node;
/*
* Queue for the requests.
*/
typedef struct req_queue {
Node front; //front node.
Node rear; //rear node.
int size; //size of the queue.
} * Queue;
/**
* Create the queue.
*/
void create(Queue queue);
/**
* For inserting an item to the queue in sorted order of file size.
* #param data
*/
void enque_SJF(Queue queue, RCB data);
#endif
queue.c
#include "queue.h"
Node temp, front1;
int count = 0;
/**
* For creating the queue.
*/
void create(Queue queue) {
queue->front = queue->rear = NULL;
queue->size=0;
}
/**
* Enqueing in the order of increasing file size.
* #param data
*/
void enque_SJF(Queue que, RCB data) {
bool found = false;
Node temp = que->front;
while (!found) {
if (que->front == NULL) { //if the queue is empty.
que->front = malloc(sizeof (struct node));
que->front->ptr = NULL;
que->front->info = data;
que->rear = que->front;
break;
} else {
if (temp->ptr == NULL) {
Node newnode = (struct node *) malloc(1 * sizeof (struct node));
newnode->info = data;
if (temp->info->sizeOfFile >= data->sizeOfFile) {
newnode->ptr = temp;
que->front = newnode;
break;
} else { //else enqueue at the rear.
temp->ptr = newnode;
}
} else {
if (temp == que->front && temp->info->sizeOfFile >= data->sizeOfFile) {
Node newnode = (struct node *) malloc(1 * sizeof (struct node));
newnode->info = data;
newnode->ptr = temp;
que->front = newnode;
break;
}
if (temp->ptr->info->sizeOfFile >= data->sizeOfFile) {
Node newnode = (struct node *) malloc(1 * sizeof (struct node));
newnode->info = data;
newnode->ptr = temp->ptr;
temp->ptr = newnode;
break;
} else
temp = temp->ptr;
}
}
}
que->size++;
}
I am trying to enqueue a new node to a queue in the function enque_SJF in queue.c file. The enqueue function is called in sws.c by the function serve_client function. Here is the sws.c There are some more functions in those files but they are not related with my problem so i didnt wrote all functions to be more simple;
#include "Queue.h"
#include "network.h"
#include "schedulers.h"
#include "shared.h"
char scheduler[4];
pthread_t tid[2];
int port;
Queue req_queue;
bool flag[2];
int turn;
int sequence_number;
void *serve_client()
{
static char *buffer; /* request buffer */
int fd;
req_queue = (struct req_queue *) malloc( sizeof (struct req_queue));
create(req_queue);
if (port != 0)
{
network_init( port ); /* init network module */
fprintf(stderr, "Connection port %d\n", port);
for( ;; )
/* main loop */
{
network_wait();
if( !buffer ) /* 1st time, alloc buffer */
{
buffer = malloc( MAX_HTTP_SIZE );
if( !buffer ) /* error check */
{
perror( "Error while allocating memory" );
abort();
}
}
for( fd = network_open(); fd >= 0; fd = network_open() ) /* get clients */
{
memset( buffer, 0, MAX_HTTP_SIZE );
if( read( fd, buffer, MAX_HTTP_SIZE ) <= 0 ) /* read req from client */
{
perror( "Error while reading request" );
abort();
}
printf("file path %s\n",buffer);
//Initializing memory for the job.
RCB request = (RCB) malloc(1 * sizeof (struct rcb));
//breaking the request in appropriate format.
request-> request_http_method = strtok(buffer, " "); //request method.
request->request_file = strtok(NULL, " /"); //request file
request->request_http_version = strtok(NULL, "\n"); //HTTP version
request->file_desc = fd;
request->level = 1; // for multilevel scheduler.
request->seq_no = sequence_number;
sequence_number++; //increment global counter.
enque_SJF(req_queue, request); //Enqueue for Shortest Job First.
}
}
}
return 0;
}
bool isValidRequest(RCB request)
{
// the request is parsed and checked the validity
}
void *SJF( )
{
// function implemented
}
int main(int argc, char **argv )
{
//default port, if no port is supplied.
/* check for and process parameters
*/
if( ( argc < 3 ) || ( sscanf( argv[1], "%d", &port ) < 1 ) || ( sscanf( argv[2], "%s", scheduler ) < 1 ) )
{
printf("port %d\n",port);
printf("port %s\n",scheduler);
printf( "usage: sms <port> <scheduler>\n" );
return 0;
}
sequence_number = 1; //counter for number of requests.
if (argc == 3)
{
port = atoi(argv[1]);
}
printf("port %d\n",port);
pthread_create(&(tid[0]), NULL, serve_client, NULL);
if(strcmp(scheduler,"SJF") ==0)
{
pthread_create(&(tid[1]), NULL, SJF, NULL);
}
else if(strcmp(scheduler,"RR")==0)
{
pthread_create(&(tid[1]), NULL, Round_Robin, NULL);
}
else if(strcmp(scheduler,"MLFB")==0)
{
pthread_create(&(tid[1]), NULL, MultilevelQueueWithFeedback, NULL);
}
else
{
printf("Scheduler Algorithm is not defined. Please enter one of them; SJF, RR, MLFB");
return 0;
}
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
return 0;
}
While adding a new node to the queueu i am getting a segmentation fault error at the following line;
que->front->ptr = NULL;
While debugging, i see that after memory allocation the address for que->front is still 0x0. Is there any suggestion why it does not allocate memory?
That is why you should always perform success check for the called function(s).
In case, if malloc() is failure, it will return a NULL pointer which gets stored in que->front. After that, without a NULL check, if you try to access
que->front->ptr
you'll be de-referencing a NULL pointer (i.e, accessing invalid memory) which invokes undefined behavior.
Always do a NULL check on the return value of malloc().
I am writting a program on doubly linked list with the following data structure:
typedef struct telephoneBookNode {
int id;
char name[NAME_LENGTH];
char telephone[TELEPHONE_LENGTH];
struct telephoneBookNode * previousNode;
struct telephoneBookNode * nextNode;
} TelephoneBookNode;
typedef struct telephoneBookList {
TelephoneBookNode * head;
TelephoneBookNode * tail;
TelephoneBookNode * current;
} TelephoneBookList;
In the following function, I read data from a text file to the linked list, the file content look like this:
/*100, Alice, 0411112222
101, Bob, 0411112222
102, Ali, 0411112223*/
TelephoneBookList * commandLoad(char* fileName) {
TelephoneBookList *(*createList)(TelephoneBookNode*, char[]) = createTelephoneBookList;
char entry[100], *temp1, *temp2;
TelephoneBookList* aList = NULL;
TelephoneBookNode* aNode = NULL;
FILE* telephoneListFile = NULL;
int countEntry = 0;
Boolean check;
telephoneListFile = fopen(fileName, "r");
if (!telephoneListFile)
return NULL;
else {
while (fgets(entry, 100, telephoneListFile)) {
temp2 = strcpy(temp2, entry);
temp1 = strtok(entry, "\n");
check = addressBookEntryCheck(temp1);
if (!check)
return NULL;
else
//here I pass aNode pointer to the below function
aList = (*createList)(aNode, temp2);
}
fclose(telephoneListFile);
printf("printed"); //This line is reached when program complied
return aList;
}
}
This is the function to create the list, problem may be here: it doesnot add new node to the list, it just replaces the first node with the new one. Finally, the linked list only has 1 record which was the last one in text file. How can I fix the code? Thank you!
TelephoneBookList * createTelephoneBookList(TelephoneBookNode* node, char entry[]) {
TelephoneBookList* aList = malloc(sizeof *aList);
TelephoneBookNode* aNode = (TelephoneBookNode*) malloc(sizeof *aNode);
char *tokens;
tokens = strtok(entry, ", ");
aNode->id = atoi(tokens);
tokens = strtok(NULL, ", ");
strcpy(aNode->name, tokens);
tokens = strtok(NULL, ", ");
strcpy(aNode->telephone, tokens); //Just assigning values to a node
//program always go to this block, means `node` is always null
if (node == NULL) {
aNode->nextNode = NULL;
aNode->previousNode = NULL;
node = aNode;
aList->current = node;
aList->head = node;
aList->tail = node;
}
else { //This block is not reached
while (node->nextNode)
node = node->nextNode;
node->nextNode = aNode;
aNode->previousNode = node;
aList->tail = node->nextNode;
}
return aList;
}
This is the function to check entry:
Boolean addressBookEntryCheck(char entry[]) {
char *tokens;
tokens = strtok(entry, ", ");
if(!tokens || strlen(tokens) < 1 || strlen(tokens) > 3)
return FALSE;
else {
if (!isNumber(tokens))
return FALSE;
else {
tokens = strtok(NULL, ", ");
if (!tokens)
return FALSE;
else
{
tokens = strtok(NULL, ", ");
if (!tokens)
return FALSE;
else if (!isNumber(tokens) || strlen(tokens) != 10)
return FALSE;
else
return TRUE;
}
}
}
}
Every time you call
createTelephoneBookList
you create a new list
TelephoneBookList* aList = malloc(sizeof *aList);
You also copy to an uninitialized pointer
temp2 = strcpy(temp2, entry);
I would suggest you create one function to create the list header, one function to add new items e.g.
aList = createList()
while (fgets(entry,sizeof(entry),fp)!=NULL)
{
if (!addEntry(aList,entry))
{
fprintf(stderr, "failed additem item %s\n", entry);
}
}
...
In addEntry parse the string
int id = 0;
char name[NAME_LENGTH];
char telephone[TELEPHONE_LENGTH];
p = strtok(entry, ","); // id
if (p != NULL)
{
id = atoi(p);
p = strtok(NULL, ","); // name, store to temporary string
if (p != NULL )
{
strcpy(name,p);
p = strtok(NULL, ","); // telephone number, store to temporary string
if ( p != NULL )
{
strcpy(telephone,p);
// here you can allocate the new node
}
}
}
// disclaimer omitted checks for length etc which any good program should have. also make sure you have room for \0
if any of the strtok above fail return 0 otherwise allocate a new entry
TelephoneBookNode* aNode = malloc(sizeof(TelephoneBookNode));
aNode->id = id;
strcpy(aNode->name, name);
strcpy(aNode->telephone, telephone);
Then add to your aList
//program always go to this block, means `node` is always null
if (node == NULL) {
....
This is because the caller of the function passed aNode and it never changes within that loop. So it will always pass same value of aNode which is NULL.
I haven't looked at the logic of your code in details, but I think you may want to pass aList->head or rather you already pass aList so just use that.