glibc detected outfile: free(): invalid pointer: - c

My code is giving glibc error.Can someone please point out my mistake.
This code is used to tokenize words. How do i solve these problems using GDB or any other tool that can be helpful. The code is given below
#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
#include <string.h>
struct token
{
char *token;
int length;
};
void freeing(gpointer item)
{
free(((struct token*)item)->token);
}
int main(int argc, char* argv[])
{
int start1 = 0, start2 = 0, i =0;
struct token *tk = NULL;
char line[256], *temp = NULL;
FILE *fp1 = NULL;
FILE *fp2 = NULL;
GSList *list = NULL, *iterator = NULL;
fp1 = fopen(argv[1], "r");
fp2 = fopen(argv[2], "w+");
if (NULL == fp1)
{
fprintf(stderr,"cant open %s",argv[1]);
return 1;
}
if (NULL == fp2)
{
fprintf(stderr,"cant open %s",argv[2]);
return 1;
}
while (1)
{
if (NULL == fgets(line, 255, fp1))
break;
tk = (struct token *)malloc(sizeof(struct token));
start1 = -1; start2 = -1;
for(temp = line,i = 0; temp[i] != '\n'; i++)
{
if ((temp[i] == ',') || (temp[i] == ' ') || (temp[i] == ';') || (temp[i] == '.'))
start2 = i;
if (start1 == start2)
continue;
tk->token = strndup(line + (start1+1), start2 - (start1+1));
tk->length = strlen(tk->token);
list = g_slist_append(list, tk);
start1 = start2;
}
tk->token = strndup(line + (start1+1), strlen(line));
tk->length = strlen(tk->token);
printf("\ntk->length : %d\n",tk->length);
list = g_slist_append(list, tk );
}
for (iterator = list; iterator; iterator = iterator->next)
{
printf("%s -> ",((struct token *)(iterator->data))->token);
printf("%d\n",((struct token*)iterator->data)->length);
}
g_slist_foreach(list, (GFunc)freeing, NULL);
fclose(fp1);
fclose(fp2);
return 0;
}

the following code has the major problems fixed, but not the logic errors in the loop :
for(int i=0, temp = line; temp[i] != '\n'; i++)
{
...
}
tk->token = strndup(line + (start1+1), strlen(line));
tk->length = strlen(tk->token);
printf("\ntk->length : %d\n",tk->length);
list = g_slist_append(list, tk );
the suggested fixes for the majority of the problems in the posted code are corrected in the following:
added final call to g_slist_free(list); so all the instances of the struct token are returned to the heap.
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
#include <string.h>
#define MAX_LINE_LEN (256)
struct token
{
char *token;
int length;
};
void freeing(gpointer item)
{
free(((struct token*)item)->token);
}
int main(int argc, char* argv[])
{
if( 3 != argc )
{ // then incorrect number of command line arguments
fprintf( stderr, "USAGE: %s <inputfile> <outputfile>\n", argv[0]);
exit( EXIT_FAILURE );
}
// implied else, correct number of command line arguments
FILE *fp1 = NULL;
FILE *fp2 = NULL;
if( NULL == (fp1 = fopen(argv[1], "r") ) )
{ // then fopen failed
fprintf( stderr, "fopen for %s for read failed\n", argv[1]);
exit( EXIT_FAILURE );
}
// implied else, fopen successful
if( NULL == (fp2 = fopen(argv[2], "w+") ) )
{ // then fopen failed
fprintf( stderr, "fopen for %s for write failed\n", argv[2]);
fclose( fp1 ); // cleanup
exit( EXIT_FAILURE );
}
// implied else, fopen successful
GSList *list = NULL;
GSList *iterator = NULL;
char line[ MAX_LINE_LEN ];
struct token *tk = NULL;
char *temp = NULL;
while ( fgets(line, sizeof(line), fp1) )
{
if( NULL == (tk = malloc(sizeof(struct token)) ) )
{ // then malloc failed
perror( "malloc for struct token failed");
fclose( fp1 );
fclose( fp2 );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
size_t start1 = 0;
size_t start2 = 0;
temp = line;
for(size_t i=0; temp[i] != '\n'; i++)
{
if ((temp[i] == ',') || (temp[i] == ' ') || (temp[i] == ';') || (temp[i] == '.'))
start2 = i;
if (start1 == start2)
continue;
tk->token = strndup(line + (start1+1), start2 - (start1+1));
tk->length = (int)strlen(tk->token);
list = g_slist_append(list, tk);
start1 = start2;
} // end for
tk->token = strndup(line + (start1+1), strlen(line));
tk->length = (int)strlen(tk->token);
printf("\ntk->length : %d\n",tk->length);
list = g_slist_append(list, tk );
} // end while
for (iterator = list; iterator; iterator = iterator->next)
{
printf("%s -> ",((struct token *)(iterator->data))->token);
printf("%d\n",((struct token*)iterator->data)->length);
}
g_slist_foreach(list, (GFunc)freeing, NULL);
g_slist_free(list);
fclose(fp1);
fclose(fp2);
return 0;
}

Related

Memory leak with getline C

I am trying to parse a config file with getline but sometimes I have a memory leak and sometimes not.
#define _GNU_SOURCE
#include "parser.h"
#include <stdlib.h>
#include <string.h>
struct global parse_global(char *line, FILE *file)
{
char *log_file = NULL;
bool log = false;
char *pid_file = NULL;
size_t len;
ssize_t nread;
char *saveptr = NULL;
while ((nread = getline(&line, &len, file)) != -1
&& strcmp(line, "[[vhosts]]\n") != 0)
{
char *arg_name = strtok_r(line, " =", &saveptr);
char *arg_value = strtok_r(NULL, " =\n", &saveptr);
if (strcmp(arg_name, "log_file") == 0)
{
log_file = strdup(arg_value);
}
else if (strcmp(arg_name, "log") == 0)
{
if (strcmp(arg_value, "true") == 0)
{
log = true;
}
else
{
log = false;
}
}
else if (strcmp(arg_name, "pid_file") == 0)
{
pid_file = strdup(arg_value);
}
}
return global_init(log_file, log, pid_file);
}
struct vhost parse_vhost(char *line, FILE *file)
{
char *server_name = "my_server";
char *port = NULL;
char *ip = NULL;
char *root_dir = NULL;
char *default_file = NULL;
size_t len;
ssize_t nread;
char *saveptr = NULL;
while ((nread = getline(&line, &len, file)) != -1
&& strcmp(line, "\n") != 0)
{
char *arg_name = strtok_r(line, " =", &saveptr);
char *arg_value = strtok_r(NULL, " =\n", &saveptr);
if (strcmp(arg_name, "server_name") == 0)
{
server_name = strdup(arg_value);
}
else if (strcmp(arg_name, "port") == 0)
{
port = strdup(arg_value);
}
else if (strcmp(arg_name, "ip") == 0)
{
ip = strdup(arg_value);
}
else if (strcmp(arg_name, "root_dir") == 0)
{
root_dir = strdup(arg_value);
}
else if (strcmp(arg_name, "default_file") == 0)
{
default_file = strdup(arg_value);
}
}
return vhost_init(server_name, port, ip, root_dir, default_file);
}
void free_global(struct global g)
{
free(g.pid_file);
free(g.log_file);
}
void free_vhost(struct vhost v)
{
free(v.server_name);
free(v.port);
free(v.ip);
free(v.root_dir);
free(v.default_file);
}
struct server *fileconfig_parser(char *file)
{
FILE *f = fopen(file, "r");
if (!f)
{
perror("cannot open file");
return NULL;
}
char *line = NULL;
size_t len = 0;
ssize_t nread = getline(&line, &len, f);
if (nread == -1 || strcmp(line, "[global]\n") != 0)
{
free(line);
perror("invalid file");
fclose(f);
return NULL;
}
struct global global = parse_global(line, f);
if (global.pid_file == NULL)
{
free_global(global);
fclose(f);
free(line);
return NULL;
}
struct vhost vhost = parse_vhost(line, f);
if (vhost.server_name == NULL || vhost.port == NULL || vhost.ip == NULL
|| vhost.root_dir == NULL)
{
free_global(global);
free_vhost(vhost);
fclose(f);
free(line);
return NULL;
}
struct server *server = server_init(global, vhost);
free(line);
fclose(f);
return server;
}
The memory come from the line allocated by getline but sometimes when I run the programme there is no memory leak and I dont know why.
It seems to me that I free line in every cases.
I also don’t know why it happened randomly.
=================================================================
==1561==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 120 byte(s) in 1 object(s) allocated from:
#0 0x7fad2918a808 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cc:144
#1 0x7fad28f0e543 in _IO_getdelim /build/glibc-SzIz7B/glibc-2.31/libio/iogetdelim.c:62
#2 0x7ffde0365e1f ([stack]+0x1ee1f)
SUMMARY: AddressSanitizer: 120 byte(s) leaked in 1 allocation(s).

Debugging: Problem with linked list linkage

I have a linked list implementation as follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CAPACITY 128
typedef struct blob blob;
struct blob {
char text[CAPACITY];
struct blob* prev;
struct blob* next;
};
static blob* create_blob() {
blob* newBlob = malloc(sizeof(blob));
if (!newBlob) {
fprintf(stderr, "%s\n", "Malloc failed");
return 0;
}
newBlob->prev = 0;
newBlob->next = 0;
memset(newBlob->text, 0, CAPACITY);
return newBlob;
}
int insertAtTail(blob* list[static 1]) {
blob* newBlob = create_blob();
if (!newBlob) {
fprintf(stderr, "%s\n", "Malloc failed");
return 0;
}
if (!*list) {
*list = newBlob;
return 1;
}
blob* lastElement = *list;
while (lastElement->next) {
// Check if linkage until last element is okay
if (lastElement != (lastElement->next)->prev) {
fprintf(stderr, "%s\n", "The next_element->prev does not point to the current element");
} else {
fprintf(stderr, "%s\n", "Okay");
}
lastElement = lastElement->next; // Find last Blob
}
lastElement->next = newBlob;
newBlob->prev = lastElement;
return 1;
}
int reversePrintBlobs(blob const list[static 1]) {
if (!list) {
fprintf(stderr, "%s\n", "list is empty");
return 1;
}
const blob* tmp = list;
size_t blobCounter = 1;
while (tmp->next) {
blobCounter++;
tmp = tmp->next;
}
while (tmp && tmp != list) {
if ((tmp->prev)->next != tmp) {
fprintf(stderr, "%s\n", "error with the linkage");
exit(1);
}
printf("#number = %zu: %s\n", blobCounter--, tmp->text);
tmp = tmp->prev;
}
return 0;
}
When I add some blobs with the following main() function, it seems like the prev member of my struct doesn't point to the previous element. That is, there is a problem with the linkage. Can anyone point out why?
int main() {
FILE* pFile = fopen("example.txt", "r");
if (!pFile) {
perror("fopen failed\n");
return EXIT_FAILURE ;
}
fseek(pFile, 0, SEEK_SET);
blob* list = create_blob();
blob* tmp = list;
while (!feof(pFile)) {
size_t noBytesRead = fread(tmp->text, sizeof(char), CAPACITY,
pFile);
if (noBytesRead != CAPACITY && !feof(pFile)) {
fprintf(stderr, "%s\n", "File read failed");
exit(EXIT_FAILURE);
}
// Append a null terminating character in the end
tmp->text[noBytesRead] = '\0';
if (!feof(pFile) && insertAtTail(&list)) {
tmp = tmp->next;
}
}
}
On the other hand, If I use the following main() everything works fine.
int main() {
blob* list = create_blob();
insertAtTail(&list);
insertAtTail(&list);
insertAtTail(&list);
insertAtTail(&list);
insertAtTail(&list);
/* code */
return 0;
}
The bug has been fixed, the new main function is the following:
int main() {
FILE* pFile = fopen("example.txt", "r");
if (!pFile) {
perror("fopen failed\n");
return EXIT_FAILURE ;
}
fseek(pFile, 0, SEEK_SET);
blob* list = create_blob();
blob* tmp = list;
int blobCounter = 1;
while (!feof(pFile)) {
size_t noBytesRead = fread(tmp->text, sizeof(char), CAPACITY,
pFile);
if (noBytesRead != CAPACITY && !feof(pFile)) {
fprintf(stderr, "%s\n", "File read failed");
exit(EXIT_FAILURE);
}
// Append a null terminating character in the end
tmp->text[noBytesRead - 1] = '\0';
if (!feof(pFile) && insertAtTail(&list)) {
blobCounter++;
tmp = tmp->next;
}
}

rename() function differs in levels of indirection from int

I'm trying to write a code that uses linked lists and files, to maintain actions (functions) that are given on a text file, instead of receiving them from the user.
For some reason i'm encountering an error which says:
"Severity Code Description Project File Line Suppression State
Error C2040 'rename': 'hw_component *(char *,char *,hw_component *)' differs in levels of indirection from 'int (const char *,const char *)' EX5_313410961 c:\users\edave\source\repos\ex5_313410961\ex5_313410961\shahar_connection.c 172"
I'm having trouble understanding if the problem is the actual function rename() or because of the actions() function.
The code is very long so ill post the relevant section only.
#define _CRT_SECURE_NO_WARNINGS
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define NAME_LENGTH 200
typedef struct hw_component
{
char name[NAME_LENGTH];
int copies;
struct hw_component *next;
}hw_component;
hw_component *create_component(char* name,int copies)
{
if (name != NULL && strlen(name) > NAME_LENGTH)
return NULL;
hw_component *comp = (hw_component*)malloc(sizeof(hw_component));
if (comp == NULL)
{
printf("Error: memory allocation failed\n");
return NULL;
}
strcpy(comp->name, name);
comp->copies = copies;
comp->next = NULL;
return comp;
}
hw_component *add_sort(hw_component* head, int copies, char *name)
{
hw_component *iter, *prev = NULL;
hw_component *new_comp = create_component(name, copies);
if (head == NULL)
return new_comp;
if (strcmp(new_comp->name, head->name) < 0)
{
new_comp->next = head;
return new_comp;
}
iter = head;
while (iter != NULL && strcmp(iter->name, new_comp->name) < 0)
{
prev = iter;
iter = iter->next;
}
prev->next = new_comp;
new_comp->next = iter;
return head;
}
hw_component *initialize(char *argv[])
{
hw_component *list_of_comp = NULL;
FILE *fp = NULL;
char dolar[2] = "$";
fp = fopen(argv[1],"r");
if (fp == NULL)
{
printf("Error: opening %s failed\n", argv[1]);
exit(1);
}
while (!feof(fp))
{
char str[400], *token, *str_num;
fgets(str, 400, fp);
int numb;
token = strtok(str,dolar);
str_num = strtok(NULL, dolar);
numb = atoi(str_num);
list_of_comp=add_sort(list_of_comp, numb, token);
}
fclose(fp);
return list_of_comp;
}
void finalize(hw_component *head, char *argv[])
{
hw_component *temp;
FILE *fp = NULL;
int temp_num;
char *str,*num_str;
fp = fopen(argv[3], "w");
if (fp==NULL)
{
printf("Error: opening %s failed\n", argv[3]);
while (head!=NULL)
{
temp = head;
head = head->next;
free(temp);
}
}
while (head!=NULL)
{
temp = head;
fprintf(fp,"%s $$$ %d\n",temp->name,temp->copies);
head = temp->next;
free(temp);
}
fclose(fp);
}
hw_component *remove_comp_by_name(hw_component *head_comp, char comp_name[NAME_LENGTH + 1])
{
hw_component *temp_ptr = head_comp;
hw_component *prev_ptr;
hw_component *zero_copies_check = head_comp;
if (head_comp == NULL)
{
return head_comp;
}
if (strcmp(temp_ptr->name, comp_name) == 0)
{
head_comp = head_comp->next;
free(temp_ptr);
return head_comp;
}
while (temp_ptr != NULL && strcmp(temp_ptr->name, comp_name) != 0)
{
prev_ptr = temp_ptr;
temp_ptr = temp_ptr->next;
}
if (temp_ptr != NULL)
{
prev_ptr->next = temp_ptr->next;
free(temp_ptr);
}
while (zero_copies_check != NULL)
{
if (zero_copies_check->copies == 0)
{
free(zero_copies_check);
}
zero_copies_check = zero_copies_check->next;
}
return head_comp;
}
hw_component *rename(char old_name[NAME_LENGTH], char new_name[NAME_LENGTH], hw_component *head_comp)
{
hw_component *temp_comp = head_comp;
int num_of_copies = 0;
if (head_comp == NULL)
{
return head_comp;
}
while (temp_comp != NULL && strcmp(temp_comp->name, old_name) != 0)
{
temp_comp = temp_comp->next;
}
num_of_copies = temp_comp->copies;
head_comp=remove_comp_by_name(head_comp, old_name);
head_comp=add_sort(head_comp, num_of_copies, new_name);
return head_comp;
}
hw_component *return_comp(hw_component *head, char name_of_comp[], int copies)
{
hw_component *temp_comp = head;
if (head == NULL)
{
return head;
}
while (temp_comp != NULL && strcmp(temp_comp->name, name_of_comp) != 0)
{
temp_comp = temp_comp->next;
}
if (temp_comp != NULL)
{
temp_comp->copies += copies;
}
else
{
add_sort(head, name_of_comp, copies);
}
return head;
}
int choose_act(char *str)
{
char init[12] = "Initialize ", rename[8]="Rename ",fire[6]="Fire ";
char retu[24] = "Returned_from_customer ", prod[12]="Production " ,fatal[19]="Fatal_malfunction ";
char finalize[] = "Finalize";
if (strcmp(str,init)==0)
return 1;
if (strcmp(str, rename)==0)
return 2;
if (strcmp(str, retu)==0 || strcmp(str, prod)==0)
return 3;
if (strcmp(str, fire)==0 || strcmp(str, fatal)==0)
return 4;
if (strcmp(str, finalize)==0)
return 5;
}
void actions(char *argv[])
{
char dolar[2] = "$";
hw_component *head;
FILE *fp = NULL;
char str[400], *token, *name, *old_name;
int choise = 0, numb;
fp = fopen(argv[2], "r");
if (fp == NULL)
{
printf("Error: opening %s failed\n", argv[2]);
exit(1);
}
while (!feof(fp))
{
fgets(str, 400, fp);
token = strtok(str,dolar);
choise = choose_act(token);
head = initialize(argv);
switch (choise)
{
case 1:
break;
case 2:
old_name = strtok(str, dolar);
name = strtok(str, dolar);
printf("%s %s", old_name, name);
head=rename(old_name,name,head);
break;
case 3:
name = strtok(str, dolar);
numb = atoi(strtok(str, dolar));
head=return_comp(head, name, numb);
break;
case 4:
name = strtok(str, dolar);
numb = atoi(strtok(str, dolar));
head=fatal_maf(head, name, numb);
break;
case 5:
finalize(head,argv);
break;
default:
break;
}
}
}
int check_argc(int argc)
{
int numb = argc;
if (argc != 3)
{
printf("Error: invalid number of arguments (<%d> instead of 3)\n", numb);
return 0;
}
return 1;
}
int main(int argc, char *argv[])
{
int res = 0;
res=check_argc(argc);
if (res == 1)
actions(argv);
return 0;
}
You library already defines a function called rename(), which is prototyped in and included by adding stdio.h, which is creating the conflict with your user-defined function.
As per the lined manual, the signature of the library-defined rename() is int rename (const char *, const char*), whereas as er your function definition, you have a signature as hw_component *rename(char *, char *, hw_component *) - which does not match and your compiler is showing you correct warning (and error) message.
Solution: Use a different name for your function.
You cannot name your custom function rename while including stdio.h, because the name collides with the standard library function rename. Name your own function something different.
The standard function is
int rename(const char *old, const char *new);
So it has type int (const char *, const char *), the same type that the compiler is complaining about a conflict with.

malloc in a loop using valgrind

I am having troubles with memory leaks (error detected by valgrind).
So here is my first function:
message *creationCellule() {
message *cellule;
cellule = (message *)malloc(sizeof(message));
if (cellule != NULL) {
cellule->dateDeb = 0;
cellule->dateFin = 0;
cellule->suivant = NULL;
memset(cellule->text, '\0', TAILLE_MAX);
}
return cellule;
}
It returns cellule which is allocated by malloc.
Now I have this:
void lectureFichier(const char *nomFichier, message **tete) {
FILE *fp = fopen(nomFichier, "r");
message *test;
test = creationCellule();
int k = 0;
if (fp != NULL) {
k = fscanf(fp, "%d %d ", &(test->dateDeb), &(test->dateFin));
while (k != EOF) {
fgets(test->text, 100, fp);
insertion(tete, test);
test = creationCellule();
k = fscanf(fp,"%d %d ", &(test->dateDeb), &(test->dateFin));
}
}
}
In which I call creationCellule() in a loop.
My problem is that, if I put free(test) inside a loop I lose all the context of my code and valgrind shows me ERROR SUMMARY:213 errors from 19 contexts.
What should I do ?
This is the complete code and the valgrind output:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "tp1.h"
message *creationCellule() {
message *cellule;
cellule = (message *)malloc(sizeof(message));
if (cellule != NULL) {
cellule->dateDeb = 0;
cellule->dateFin = 0;
cellule->suivant = NULL;
memset(cellule->text, '\0', TAILLE_MAX);
}
return cellule;
}
message **recherche(message *tete, int date) {
message **prec = tete;
message *cour = *tete;
while (cour != NULL && cour->dateDeb < date) {
prec = &(cour->suivant);
cour = cour->suivant;
}
return prec;
}
void insertion(message **tete, message *cellule) {
message **prec;
if (cellule != NULL) {
prec = recherche(tete, cellule->dateDeb);
cellule->suivant = *prec;
*prec = cellule;
}
}
void lectureFichier(const char *nomFichier, message **tete) {
FILE *fp = fopen(nomFichier, "r");
message *test;
test = creationCellule();
int k = 0;
if (fp != NULL) {
k = fscanf(fp,"%d %d ", &(test->dateDeb), &(test->dateFin));
while (k != EOF) {
fgets(test->text, 100, fp);
insertion(tete, test);
test = creationCellule();
k = fscanf(fp,"%d %d ", &(test->dateDeb), &(test->dateFin));
}
}
}
void affichageListe(message **tete) {
if (tete != NULL) {
message *tmp = *tete;
while (tmp != NULL) {
//printf("jam ktu\n");
printf("DateDeb = %d \n", tmp->dateDeb);
printf("DateFin = %d \n", tmp->dateFin);
printf("Text = %s \n", tmp->text);
tmp = tmp->suivant;
}
}
}
void suppression(message **tete, int valeur, int dateDeb) {
message **prec;
prec = recherche(tete, dateDeb);
//printf("Prec text: %s , prec dateFin: %d\n", (*prec)->text, (*prec)->dateFin);
if ((*prec) != NULL && (*prec)->dateFin == valeur) {
(*prec) = (*prec)->suivant;
}
}
void supprimeObsoletes(message **tete) {
message *pt = *tete;
time_t temps;
struct tm *date;
int intNum;
temps = time(NULL);
date = localtime(&temps);
char buffer[9];
if ((date->tm_mon) < 10) {
sprintf(buffer, "%d0%d%d", date->tm_year + 1900, date->tm_mon + 1, date->tm_mday);
} else {
sprintf(buffer, "%d%d%d", date->tm_year + 1900, date->tm_mon + 1, date->tm_mday);
}
intNum = atoi(buffer);
while (pt != NULL) {
if ((pt->dateFin) < intNum) {
printf("KTU HYB %s\n", pt->text);
suppression(tete, pt->dateFin, pt->dateDeb);
}
pt = pt->suivant;
}
}
void changeDate(int dateChange, int dateInit, message **tete) {
message *point = *tete;
//printf("Kjo eshte tete %p:\n", (*point));
while (point != NULL) {
if ((point->dateDeb) == dateInit) {
printf("%d\n", point->dateDeb);
printf("%s\n", point->text);
point->dateDeb = dateChange;
}
point = point->suivant;
}
}
int main(int argc, char *argv[]) {
const char *name = argv[1];
message *pointeur = NULL;
message **tete = &pointeur;
int dateInit = 19973012;
int dateChange = 20003008;
FILE *fp = fopen(name, "r");
lectureFichier(name, tete);
//changeDate(dateChange, dateInit, tete);
supprimeObsoletes(tete);
affichageListe(tete);
return 0;
}
The header: tp1.h
#ifndef TP1_TEST_H
#define TP1_TEST_H
#define TAILLE_MAX 100
typedef struct cell {
int dateDeb;
int dateFin;
char text[TAILLE_MAX];
struct cell *suivant;
} message;
message *creationCellule();
message **recherche(message **tete, int date);
void affichageListe(message **tete);
void insertion(message **tete, message *cellule);
void lectureFichier(const char * nomFichier, message **tete);
The .txt file (added in execution)
19973012 20220512 TEXT 1
19980511 19001203 THIS
20011102 20301123 HOUSE
20020809 20301025 HELP
Valgrind output:
Function lectureFichier does not free unused nodes properly.
Here is a corrected version:
void lectureFichier(const char *nomFichier, message **tete) {
FILE *fp = fopen(nomFichier, "r");
if (fp != NULL) {
for (;;) {
message *node = creationCellule();
if (fscanf(fp, "%d%d %99s", &node->dateDeb, &node->dateFin, node->text) == 3) {
insertion(tete, node);
} else {
free(node);
break;
}
}
}
}
the following proposed code:
cleanly compiles
properly handles errors
removed unused code
does NOT cleanup the linked list when an error occurs -- you will need to add that
and now, the proposed code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#ifndef TP1_TEST_H
#define TP1_TEST_H
#define TAILLE_MAX 100
struct cell
{
int dateDeb;
int dateFin;
char text[TAILLE_MAX];
struct cell * suivant;
};
typedef struct cell message;
message * creationCellule( void );
message ** recherche( message ** tete, int date );
void affichageListe( message ** tete );
FILE * ecrireFichier( message ** tete );
void dateNonExpires( message ** tete );
#endif // TPI_TEST_H
message * creationCellule()
{
message * cellule = malloc(sizeof(message));
if( !cellule )
{
perror( "malloc failed" );
exit( EXIT_FAILURE );
}
cellule->dateDeb = 0;
cellule->dateFin = 0;
cellule->suivant = NULL;
return cellule;
}
message ** recherche( message ** tete, int date )
{
message ** prec = tete;
message * cour = *tete;
while( cour != NULL && cour->dateDeb < date )
{
prec = &(cour->suivant);
cour = cour->suivant;
}
return prec;
}
void insertion(message ** tete, message * cellule)
{
(void)tete;
(void)cellule;
// insert code that does something reasonable
}
void lectureFichier(const char * nomFichier, message ** tete)
{
FILE * fp = fopen(nomFichier, "r");
if( !fp )
{
perror( "fopen failed" );
exit( EXIT_FAILURE );
}
test = creationCellule();
while( fscanf(fp,"%d %d ", &(test->dateDeb), &(test->dateFin)) == 2 )
{
fgets(test->text, 100, fp);
insertion(tete, test);
test = creationCellule();
}
}
void affichageListe( message ** tete )
{
if( tete )
{
message * tmp = *tete;
while( tmp )
{
//printf("jam ktu\n");
printf( "DateDeb = %d \n", tmp->dateDeb );
printf( "DateFin = %d \n", tmp->dateFin );
printf( "Text = %s \n", tmp->text );
tmp = tmp->suivant;
}
}
}
void suppression( message**tete, int valeur, int dateDeb )
{
message **prec;
prec = recherche( tete, dateDeb );
//printf("Prec text: %s , prec dateFin: %d\n",(*prec)->text,(*prec)->dateFin);
if( (*prec) != NULL && (*prec)->dateFin == valeur )
{
(*prec)=(*prec)->suivant;
}
}
void supprimeObsoletes(message **tete)
{
message *pt = *tete;
time_t temps;
struct tm *date;
temps=time(NULL);
date=localtime(&temps);
char buffer[9];
if((date->tm_mon)<10)
{
sprintf(buffer,"%d0%d%d",date->tm_year + 1900,date->tm_mon +1,date->tm_mday);
}
else
{
sprintf(buffer,"%d%d%d",date->tm_year + 1900,date->tm_mon +1,date->tm_mday);
}
int intNum=atoi(buffer);
while( pt )
{
if( (pt->dateFin) < intNum )
{
printf( "KTU HYB %s\n", pt->text );
suppression( tete, pt->dateFin, pt->dateDeb );
}
pt=pt->suivant;
}
}
int main(int argc, char * argv[])
{
if( argc != 2 )
{
fprintf( stderr, "USAGE: %s filename\n", argv[0] );
exit( EXIT_FAILURE );
}
const char * name = argv[1];
message * pointeur = NULL;
lectureFichier( name, &pointeur );
supprimeObsoletes( &pointeur );
affichageListe( &pointeur );
while( pointeur )
{
message *current = pointeur;
pointeur = pointeur->suivant;
free( current );
}
return 0;
}

Assigning data to 2D array and displaying it C

I am writing a program, that will open csv file and save data to 3D array.
Most of code works pretty good, but I have a problem with assiging records to 2D array.
Here is a code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FILE_MODE "r"
/*
Explode string with given token and assign result to list variable
*/
int explode(const char *src, const char *tokens, char ***list, size_t *len)
{
if(src == NULL || list == NULL || len == NULL) {
return 0;
}
char *str, *copy, **_list = NULL, **tmp;
*list = NULL;
*len = 0;
copy = strdup(src);
if(copy == NULL)
return 1;
str = strtok(copy, tokens);
if(str == NULL) {
goto free_and_exit;
}
_list = realloc(NULL, sizeof *_list);
if(_list == NULL) {
goto free_and_exit;
}
_list[*len] = strdup(str);
if(_list[*len] == NULL)
goto free_and_exit;
(*len)++;
while((str = strtok(NULL, tokens)))
{
tmp = realloc(_list, (sizeof *_list) * (*len + 1));
if(tmp == NULL)
goto free_and_exit;
_list = tmp;
_list[*len] = strdup(str);
if(_list[*len] == NULL)
goto free_and_exit;
(*len)++;
}
free_and_exit:
*list = _list;
free(copy);
return 2;
}
/*
Exploding lines in CSV file
*/
const char* getfield(char* line, int num)
{
const char* tok;
for (tok = strtok(line, ";");
tok && *tok;
tok = strtok(NULL, ";\n"))
{
if (!--num)
return tok;
}
return NULL;
}
int main()
{
FILE *stream;
char fileName[256], table[256], line[256],
**list, **columns, **data;
size_t length;
printf("Witaj uzytkowniku! Podaj nazwe pliku z rozszerzeniem .csv. \n");
scanf("%s", fileName);
explode(fileName, ".", &list, &length);
strcpy(table, list[0]);
stream = fopen("file.csv", FILE_MODE); // not to write path every single time
if (stream == NULL) {
printf("Nie moge otworzyc pliku %s do odczytu!\n", fileName);
exit(1);
}
fgets(line, sizeof line, stream);
explode(line, ";", &columns, &length);
int recordNumber = 0
,columnNumber = 0;
while (fgets(line, sizeof line, stream))
{
char* tmp = strdup(line);
if (getfield(tmp, recordNumber) != NULL) {
columnNumber++;
}
recordNumber++;
free(tmp);
}
fseek(stream, 0, SEEK_SET); // Go to beginning of file
fgets(line, 1024, stream);
int i = 0 // Number of records
,h = 0; // number of columns
char **records[recordNumber][columnNumber];
length = 0;
char *tmp[recordNumber];
// Here I get number of lines and columns in csv file to make 3D array??
while (fgets(line, sizeof line, stream) && i < recordNumber)
{
tmp[i] = strdup(line);
explode(tmp[i], ";", &data, &length);
for (h = 0; h < columnNumber; h++)
{
memcpy(records[i][h], data[h], sizeof(data[h]));
}
i++;
}
for (i = 0; i < recordNumber; i++)
{
for (h = 0; h < columnNumber; h++)
{
printf("%s ", records[i][h][0]);
}
printf("\n");
}
fclose(stream);
return EXIT_SUCCESS;
}
Problem starts, when I try do a loop, that assign data to array:
while (fgets(line, sizeof line, stream) && i < recordNumber)
{
tmp[i] = strdup(line);
explode(tmp[i], ";", &data, &length);
for (h = 0; h < columnNumber; h++)
{
memcpy(records[i][h], data[h], sizeof(data[h]));
}
i++;
}
I tried to use memcpy and strcpy, but none works correctly - I am pretty sure.
When code goes to these lines, there is an error: segmentation fault (core dumping).
All i want to achieve is to fill this array with data from csv file and print it.
Thanks for your help! :)
EDIT:
explode function is not mine. Probably, I found it somewhere on stackoverflow.
When, it comes to the code, after little change, it works
char records[recordNumber][columnNumber][1024];
length = 0;
char *tmp[recordNumber];
while (fgets(line, sizeof line, stream) && i < recordNumber)
{
tmp[i] = strdup(line);
explode(tmp[i], ";", &data, &length);
for (h = 0; h < columnNumber; h++)
{
strcpy(records[i][h], data[h]);
}
i++;
}
Read each line of the file with fgets. strpbrk can be used to find the delimiters. Two pointers can be used to get the number of characters between the delimiters. Then allocate memory and use memcpy to copy the field to the allocated memory.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char ***strpdlm ( char *pdelim, int skip);
char ***freedlm ( char ***ppp);
int main()
{
char ***expld = NULL;
int line = 0;
int field = 0;
//last argument of 1 is skip consecutive delimiters. 0 do not skip
expld = strpdlm ( ";\n", 1);// delimiters semicolon and newline
//print each extracted string
line = 0;
if ( expld) {//not null
while ( expld[line]) {//not null
field = 0;
printf ( "\nfields for line %d\n", line);
while ( expld[line][field]) {//not null
printf ( "expld[%d][%d] %s\n", line, field, expld[line][field]);
field++;
}
line++;
}
}
//free memory and set NULL
expld = freedlm ( expld);
return 0;
}
char ***freedlm ( char ***ppp) {
size_t each = 0;
size_t item = 0;
if ( ppp) {
while ( ppp[each]) {
item = 0;
while ( ppp[each][item]) {
free ( ppp[each][item]);
item++;
}
free ( ppp[each]);
each++;
}
free ( ppp);
}
return NULL;
}
char ***strpdlm ( char *pdelim, int skip) {
char ***xpld = NULL;
char ***temprecord = NULL;
char **tempfield = NULL;
char *pnt = NULL;
char *cur = NULL;
char line[1024] = "";
int span = 0;
int len = 0;
int record = 0;
int field = 0;
FILE *pf = NULL;
if ( ( pf = fopen ( "file.csv", "r")) == NULL) {
perror ( "could not open \"file.csv\"");
return NULL;
}
if ( pdelim) {
while ( fgets ( line, sizeof line, pf)) {
//make sure each line ends with \n
len = strcspn ( line, "\n");
if ( len + 1 < sizeof line) {
line[len] = '\n';
line[len + 1] = '\0';
}
//allocate record + 2 pointers
if ( ( temprecord = realloc ( xpld, ( record + 2) * sizeof ( *xpld))) == NULL) {
fprintf ( stderr, "problem realloc records\n");
fclose ( pf);
return xpld;
}
xpld = temprecord;
xpld[record] = NULL;
field = 0;
cur = line;//cur points to line
while ( ( pnt = strpbrk ( cur, pdelim))) {
if ( pnt != cur || !skip) {
if ( ( tempfield = realloc ( xpld[record], ( field + 2) * sizeof ( **xpld))) == NULL) {
fprintf ( stderr, "problem realloc fields\n");
fclose ( pf);
return xpld;
}
xpld[record] = tempfield;
xpld[record][field] = NULL;
if ( pnt) {
span = pnt - cur;
}
else {
span = strlen ( cur);
}
if ( ( xpld[record][field] = malloc ( span + 1)) == NULL) {
fprintf ( stderr, "problem malloc\n");
fclose ( pf);
return xpld;
}
memcpy ( xpld[record][field], cur, span);
xpld[record][field][span] = '\0';
field++;
xpld[record][field] = NULL;//sentinel NULL
}
cur = pnt + 1;//set cur to point to next field
}
record++;
xpld[record] = NULL;//sentinel NULL
}
}
fclose ( pf);
return xpld;
}

Resources