Context: Explanation of pointing to same address problem
compile:
gcc \
-Wpointer-arith -Wendif-labels \
-Wimplicit-fallthrough -Wmissing-format-attribute \
-Wcast-function-type -Wshadow=compatible-local \
-Wformat-security -Wno-format-truncation -Wno-stringop-truncation \
main.c &&./a.out dat/test.csv
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<errno.h>
enum {MAXB = 128, NELEM = 10};
typedef struct data_t{
char *name;
int id;
double balance;
}data_t;
int main(int argc,char **argv)
{
if(argc < 2){
printf("No file input.foramt a.out filename. %s\n",argv[1]);
exit(EXIT_FAILURE);
}
FILE *fp = fopen(argv[1],"r");
if(fp == NULL){
printf("file not found\n");
exit(EXIT_FAILURE);
}
char buffer[MAXB] = "";
const char *delim = ",\n";
int index = 0;
data_t **array = malloc(NELEM * sizeof *array);
if(!array){ /* validate EVERY allocation */
perror("malloc-array failed\n");
exit(EXIT_FAILURE);
}
/* protect the allocation bounds, you only have NELEM pointers */
while (index < NELEM && fgets(buffer,sizeof buffer,fp))
{
data_t customer;
size_t len = 0;
char *tmp; /* temporary pointer to use w/strtok() */
tmp = strtok(buffer,delim); /* token for name */
if(!tmp) /* validate token */
{
fputs("error: strtok() name.\n",stderr);
exit(EXIT_FAILURE);
}
len = strlen(tmp); /* get length */
customer.name = malloc(len+1); /* allocate for string */
if(!customer.name)
{
perror("malloc-customer.name\n");
exit(EXIT_FAILURE);
}
memcpy(customer.name,tmp, len +1); /* copy tmp to .name */
if(!(tmp = strtok(NULL,delim))) /* token & validations */
{
fprintf(stderr,"error: strtok() -id.\n");
exit(EXIT_FAILURE);
}
/* MINIMAL conversion validation with sscanf() */
if(sscanf(tmp,"%d",&customer.id) != 1){
fprintf(stderr,"error: invalid integer value for line[%d]\n",index+1);
continue;
/* exit(EXIT_FAILURE); */
}
if(!(tmp = strtok(NULL,delim))){
fprintf(stderr,"\nerror: strtok()-balance shuld have more line\n");
continue;
// exit(EXIT_FAILURE);
}
if(sscanf(tmp,"%lf", &customer.balance) != 1){
fprintf(stderr,"error: invalid float value for line[%d]\n", index+1);
/* exit(EXIT_FAILURE); */
continue;
}
array[index] = malloc(sizeof *array[index]); /* allocate struct */
if(!array[index]){ /* validate!! */
perror("malloc-array[index]");
exit(EXIT_FAILURE);
}
*array[index] = customer; /* assign struct */
index += 1;
}
fclose(fp);
int i;
printf("\nname\tid\t balance\n\n");
for(i = 0; i< index; i++)
printf("%s \t%d\t%f\n",array[i]->name,array[i]->id,array[i]->balance);
for(i = 0; i< index; i++)
{
if(array[i]->name)
free(array[i]->name); /* free allocated block for name */
if(array[i])
free(array[i]); /* free allocated array index */
}
free(array);
exit(EXIT_FAILURE);
}
cat dat/test.csv returns
name,id,balance
test1,11,1.2334
test2,12,1.133
test3,13,1.3334
test4,14,1.4334
command valgrind -s --leak-check=full ./a.out dat/test.csv
output:
==494197== Memcheck, a memory error detector
==494197== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==494197== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==494197== Command: ./a.out dat/test.csv
==494197==
error: invalid integer value for line[1]
name id balance
test1 11 1.233400
test2 12 1.133000
test3 13 1.333400
test4 14 1.433400
==494197== Memcheck, a memory error detector
==494197== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==494197== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==494197== Command: ./a.out dat/test.csv
==494197==
error: invalid integer value for line[1]
name id balance
test1 11 1.233400
test2 12 1.133000
test3 13 1.333400
test4 14 1.433400
==494197==
==494197== HEAP SUMMARY:
==494197== in use at exit: 5 bytes in 1 blocks
==494197== total heap usage: 13 allocs, 12 frees, 5,797 bytes allocated
==494197==
==494197== 5 bytes in 1 blocks are definitely lost in loss record 1 of 1
==494197== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==494197== by 0x10951D: main (in /home/jian/helloc/a.out)
==494197==
==494197== LEAK SUMMARY:
==494197== definitely lost: 5 bytes in 1 blocks
==494197== indirectly lost: 0 bytes in 0 blocks
==494197== possibly lost: 0 bytes in 0 blocks
==494197== still reachable: 0 bytes in 0 blocks
==494197== suppressed: 0 bytes in 0 blocks
==494197==
==494197== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)