i wrote a linked list meant to store cpu information. this is a simple input-and-store program and unfortunately get memory leaks. here is the code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
unsigned input_unsigned_number(void);
double input_double_number(void);
char * gets_s(char ** ptr_to_ptr);
struct cpu_specs {
/* cpu_specs is a tag of structure */
char * vendor_id;
char * cpu_model;
double cpu_MHz;
unsigned cache_size: 16; /* set up 16-bit fields */
unsigned clflush_size: 16; /* set up 16-bit fields */
struct cpu_specs * next;
};
/* set up the structure declaration */
int main(void) {
struct cpu_specs * head_to_cpu_stru = NULL;
struct cpu_specs * previous, * current, * temp;
char MAX_input[1024];
fputs("Input the vendor's id(input sole [Enter] to terminate input): ", stdout);
current = (struct cpu_specs * ) malloc(sizeof(struct cpu_specs));
/* allocates sizeof(struct cpu_specs) bytes in the midst of uninitialized memory. */
while (gets_s( & (current - > vendor_id)) != NULL &&
current - > vendor_id[0] != '\0') {
if (head_to_cpu_stru == NULL) head_to_cpu_stru = current;
/* assign the first allocated momery of a pointer to structure cpu_specs to head_to_cpu_stru. */
else previous - > next = current;
/* assign the non-first allocated momery of a pointer to structure cpu_specs to previous->next. */
current - > next = NULL;
/* set current->next to be NULL. */
fputs("Input the cpu model(input sole [Enter] to terminate input): ", stdout);
if (gets_s( & (current - > cpu_model)) == NULL &&
current - > cpu_model[0] == '\0') break;
fputs("Input the cpu_MHz(cpu_MHz must be multiplier of 100): ", stdout);
current - > cpu_MHz = input_double_number();
fputs("Input the cache_size(cache_size<=65536 and cache_size must be power of 2): ", stdout);
current - > cache_size = input_unsigned_number();
fputs("Input the clflush_size(clflush_size<=65536 and clflush_size must be power of 2): ", stdout);
current - > clflush_size = input_unsigned_number();
temp = current;
current = (struct cpu_specs * ) malloc(sizeof(struct cpu_specs));
/* allocates sizeof(struct cpu_specs) bytes in the midst of uninitialized memory again. */
previous = temp;
/* assign the current allocated memory of a pointer to structure cpu_specs to previous. */
}
/* gather and store cpu specs from your input. */
if (head_to_cpu_stru == NULL) puts("No any cpu specs.!");
else {
puts("here are all cpu speces:");
puts("vendor_id\tcpu_model\tcpu_MHz\tcache_size\tclflush_size");
}
for (current = head_to_cpu_stru; current - > next != NULL; current = current - > next)
printf("%s\t%s\t%.2fMHz\t%uKB\t%uKB\n", current - > vendor_id,
current - > cpu_model, current - > cpu_MHz, current - > cache_size, current - > clflush_size);
/* show cpu specs in a list */
for (current = head_to_cpu_stru; current - > next != NULL; current = current - > next)
free(current);
puts("program done!");
return 0;
}
double input_double_number(void) {
double decimal_number;
_Bool input_check;
while ((input_check = fscanf(stdin, "%lf", & decimal_number)) != 1 &&
fmod(decimal_number, 100.00) == 0) {
if (input_check != 1) scanf("%*s");
fprintf(stdout, "invalid input, enter this number again: ");
}
return decimal_number;
}
unsigned input_unsigned_number(void) {
unsigned decimal_number;
_Bool input_check;
while ((input_check = fscanf(stdin, "%u", & decimal_number)) != 1 &&
decimal_number <= 65536 && (decimal_number & decimal_number - 1) == 0) {
if (input_check != 1) scanf("%*s");
fprintf(stdout, "invalid input, enter this number again: ");
}
return decimal_number;
}
char * gets_s(char ** ptr_to_ptr) {
unsigned i;
void * alloc_check;
char MAX_input[1024];
if (fgets(MAX_input, 1024, stdin)) {
for (i = 0; MAX_input[i] != '\n' && MAX_input[i] != '\0' && i < 1024; i++);
if (MAX_input[i] == '\n') MAX_input[i] = '\0';
if (( * ptr_to_ptr = (char * ) malloc((strlen(MAX_input) + 1) * sizeof(char))) == NULL)
/*because the spaces where pointers inside structure point are not allocated and initialized. */
{
perror("fail to allocation.\n");
exit(EXIT_FAILURE);
}
strcpy( * ptr_to_ptr, MAX_input);
return *ptr_to_ptr;
} else return NULL;
}
input_double_number()
, input_decimal_number()
are input processings. gets_s()
take functionality of initialization memory space where vendor_id
, cpu_model
points as well as string input.
i could input the first entry in list. when it comes to the second one, it couldn't go further and crash in memory leaks. here is GDB LeakSanitizer:
Direct leak of 40 byte(s) in 1 object(s) allocated from:
#0 0x7fe5e708dbc8 in malloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)
#1 0x7fe5e79fe8da in main /home/brushmonk/linkedlist.c:44
#2 0x7fe5e6c570b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
Direct leak of 40 byte(s) in 1 object(s) allocated from:
#0 0x7fe5e708dbc8 in malloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)
#1 0x7fe5e79fe5ab in main /home/brushmonk/linkedlist.c:23
#2 0x7fe5e6c570b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
Indirect leak of 9 byte(s) in 2 object(s) allocated from:
#0 0x7fe5e708dbc8 in malloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)
#1 0x7fe5e79ff286 in gets_s /home/brushmonk/linkedlist.c:93
#2 0x7fe5e79fe917 in main /home/brushmonk/linkedlist.c:26
#3 0x7fe5e6c570b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
Indirect leak of 3 byte(s) in 1 object(s) allocated from:
#0 0x7fe5e708dbc8 in malloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)
#1 0x7fe5e79ff286 in gets_s /home/brushmonk/linkedlist.c:93
#2 0x7fe5e79fe6b2 in main /home/brushmonk/linkedlist.c:35
#3 0x7fe5e6c570b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
SUMMARY: AddressSanitizer: 92 byte(s) leaked in 5 allocation(s).
did i write a wrong gets_s()
function and use a pointer to pointer as argument to lead crash?