I have written some C-code and I'm getting compiler warnings when I try to free previously allocated data.
The warnings (in Visual Studio 2022) are:
Warning C6001 Using uninitialized memory '*experiments.mass'.
Warning C6001 Using uninitialized memory '*experiments.length'.
The program is reading from txt file named, "result," and checks the measurements to calculate spring constant.
The warning is on the lines:
free(experiments[i].mass); //free all the data that saved by the order of the saving
free(experiments[i].length);
Here is a compilable code section that reproduces the diagnostics:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <crtdbg.h>
#define GRAVITY 9.81
typedef struct {
double* mass;
double* length;
int exp_num;
int numMeasurements;
double k;
double r2;
} Exp_t;
void errorList(int error_num);
/*the function get the file name, open the file and read ho many times the word experiment is shown
in the end the function return int num that count how many times the word is in the file*/
int counting_experiment(const char* file_name);
/*the same as counting experiment but check what is the maximum measurements for each experiment*/
int counting_measurements(const char* file_name);
/*read string that the user input and give back int number that the string contains.
if the string have char that is not number it brings back error.*/
int StringToInt(const char* str);
/*the function get the Exp_t array and the number of experiments and sorting the exp_num from the
smallest to the biggest*/
void sortExperiments(Exp_t* experiments, int numExperiments);
/*the function takes the file name and the Exp_t array, and experiment and measurements counters
the function go over the file and put in the structure all of the experiments data.*/
void Read_File(const char* file_name, Exp_t* experiments, int* numExperiments, int max_measuerment);
/*this function get char from the user and check if he want to continue or not.
if the char is illegal it gives an error massage if it is legal char it make the relevant commands. */
char prog_continue(char user_input);
/*the function calculate the spring constant and get the specific struct of Exp_t
that relevant to the user input experiment number. the function output is print of the calculated value
and saving k to the correct struct in order to be able use it later*/
void calculateSpringConstant(Exp_t* experiment, int max_measurement);
/*get the structure array and print all the information that relevant
to the [i] place in the structure*/
void Print_File(const char* file_name, const Exp_t* experiments, int numExperiments);
int main() {
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
const char* file_name = "Results.txt";
const char* Proc_File_Name = "processed_206523649.txt";
Exp_t* experiments;
int numExperiments = 0;
int counting_exp = counting_experiment(file_name);
experiments = (Exp_t*)calloc(counting_exp, sizeof(Exp_t));
if (experiments == NULL) exit(1); // check if the calloc worked.
int counting_measurement = counting_measurements(file_name);
Read_File(file_name, experiments, &numExperiments, counting_measurement);
char selected_exp_str[50];
int selected_exp;
char to_continue = '\0';
do
{
printf_s("What experiment do you want to analyze: \n");
scanf_s("%s", selected_exp_str, (unsigned int)sizeof(selected_exp_str) - 1);
selected_exp = StringToInt(selected_exp_str); // this part check if the input is a positive int
if (selected_exp < 0)
{
errorList(1);
while (getchar() != '\n');
continue;
}
int exp_index = -1;
for (int i = 0; i < numExperiments; i++) //the loop check for match between user input to exp_num
{
if (experiments[i].exp_num == selected_exp) //check if there is match between the user input to the available exp
exp_index = i; // if there is sa match change the flag
}
if (exp_index == -1) { // if the flag hasn't changed print error.
printf_s("Experiment %s does not exist in Result.txt. Please select one of the following experiments:\n", selected_exp_str);
for (int i = 0; i < numExperiments; i++)
printf_s("%d\n", experiments[i].exp_num);
}
else
calculateSpringConstant(&experiments[exp_index], counting_measurement); //calculate the k and r2 for the selected exp
} while (prog_continue(to_continue) != 'n'); //running until the user input for ending is 'n'
sortExperiments(experiments, numExperiments); // Sort experiments array before printing
Print_File(Proc_File_Name, experiments,numExperiments);
printf_s("Experiment data saved to processed_206523649.txt.\n");
for (int i = 0; i < counting_exp; i++)
{
free(experiments[i].mass); //free all the data that saved by the order of the saving
free(experiments[i].length);
}
free(experiments);
return 0;
}
int counting_experiment(const char* file_name) {
FILE* file;
fopen_s(&file, file_name, "rt");
if (!file) exit(1);
char line[100];
int current_exp = -1;
int exp_counting = 0;
while (fgets(line, sizeof(line), file)) {//the loop go over each raw and check if experiment word is in it. if yes it add 1 to the counter
if (sscanf_s(line, "experiment_%d", ¤t_exp) == 1)
exp_counting++;
}
return exp_counting;
}
int counting_measurements(const char* file_name){
FILE* file;
fopen_s(&file, file_name, "rt");
if (!file) exit(1);
char line[100];
int counter = 0, temp_counter = 0, current_exp = -1;
while (fgets(line, sizeof(line), file)) {
if (line[0] == 'm') {
temp_counter++; //running on all the measurement line till End and plus 1 to the temp counter on each line
continue;
}
if (temp_counter > counter) {
counter = temp_counter; // if the temp is bigger update the counter. in the end counter will be the biggest
temp_counter = 0;
}
}
return counter;
}
void Read_File(const char* file_name, Exp_t* experiments, int* numExperiments, int max_measurement) {
FILE* file;
fopen_s(&file, file_name, "rt");
if (!file) exit(1); // open the file to read only and crush if it not find the file
int current_exp = -1;
char line[100];
while (fgets(line, sizeof(line), file)) { //loop running on each line until EOF
if (sscanf_s(line, "experiment_%d", ¤t_exp) == 1) //if experiment found set the value for the structure
{
experiments[*numExperiments].exp_num = current_exp;
experiments[*numExperiments].mass = (double*)calloc(max_measurement, sizeof(double));
experiments[*numExperiments].length = (double*)calloc(max_measurement, sizeof(double));
if (experiments[*numExperiments].mass == NULL || experiments[*numExperiments].length == NULL ){
exit(1); //save memory for the max measurements that could be and check if it worked
}
experiments[*numExperiments].k = 0.0;
experiments[*numExperiments].r2 = 0.0; //initialize k and r2 for each exp to 0
experiments[*numExperiments].numMeasurements = 0;
(*numExperiments)++;
}
if (line[0] == 'm')
{
double mass, length; //if line is start with m it saves the data for mass and length to the structure
if (sscanf_s(line, "m:%lf l:%lf", &mass, &length) == 2)
{
experiments[*numExperiments - 1].mass[experiments[*numExperiments - 1].numMeasurements] = mass;
experiments[*numExperiments - 1].length[experiments[*numExperiments - 1].numMeasurements] = length;
experiments[*numExperiments - 1].numMeasurements++;
}
}
else if (strcmp(line, "end\n") == 0) { //if the line is end initialize the counter
current_exp = -1;
}
}
fclose(file);
}
I expected to get all the data free and it did work when the code is like this.
However, I don't want the warnings but, on the other hand, when I free the data without loop in this way:
free(experiments->mass);
free(experiments->length);
free(experiment);
then the compiler doesn't show any error or warning but the _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
shows a memory leak.