Please help, I can't figure out how to free memory correctly. There is a code below
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INT_MSG_LEN 25;
enum {NO_ERROR = 0,
ERROR_INPUT = 100,
ERROR_LEN = 101};
static const char *error_texts[] = { "Error input!",
"Error lenghts!"};
void shift(char *msgEnc, char *msg, char *msgRes, char *mainMsg, char *alphabet, int offset);
void report_error(int error);
void print_error(int error);
int get_sameletters(char *msg, char *msgRes, int offset);
int get_letter(char letter, char *alphabet);
int compare(char *msgEnc, char *msg, char *msgRes, char *alphabet, int offset);
char *read_Input_Msg(int *msglen);
char rotate(char *original, int offset);
int main(int argc, char *argv[])
{
int ret = NO_ERROR;
char *msgEnc, *msg, alphabet[53] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
int msgEncLen, msgLen;
msgEnc = msg = NULL;
msgEncLen = msgLen = 0;
msgEnc = read_Input_Msg(&msgEncLen);
if (msgEnc)
msg = read_Input_Msg(&msgLen);
if (msgEnc == NULL || msg == NULL)
ret = ERROR_INPUT;
else if (msgEncLen != msgLen)
ret = ERROR_LEN;
char msgRes[msgEncLen], mainMsg[msgEncLen];
if (ret == NO_ERROR)
shift(msgEnc, msg, msgRes, mainMsg, alphabet, msgEncLen);
else
print_error(ret);
free(msgEnc);
free(msg);
return ret;
}
void shift(char *msgEnc, char *msg, char *msgRes, char *mainMsg, char *alphabet, int offset)
{//function for decoding text by a defined offset
int dis;
dis = compare(msgEnc, msg, msgRes, alphabet, offset);
for (int i = 0; i<offset; i)
mainMsg[i] = msgEnc[i] dis;
rotate(mainMsg, offset);
for(int i = 0; i<offset; i)
printf("%c", mainMsg[i]);
printf("\n");
}
void report_error(int error)
{//prints error
if (error >= ERROR_INPUT && error <= ERROR_LEN)
fprintf(stderr, "%s\n", error_texts[error - ERROR_INPUT]);
}
void print_error(int error)
{//what error it is
switch (error){
case ERROR_INPUT:
report_error(ERROR_INPUT);
break;
case ERROR_LEN:
report_error(ERROR_LEN);
break;
}
}
int get_sameletters(char *msg, char *msgRes, int offset)
{//gets count of sameletters between two strings
int sameLetters = 0;
for (int i = 0; i<offset-1; i){
if (msg[i] == msgRes[i])
sameLetters ;
}
return sameLetters;
}
int get_letter(char letter, char *alphabet)
{
int k = 0;
for (int i=0; alphabet[i]; i){
if (letter == alphabet[i])
k = i;
}
return k;
}
int compare(char *msgEnc, char *msg, char *msgRes, char *alphabet, int offset)
{//calculate a distance between first input string and string what will get after decryption
int distance, max_letters = 0;
for (int i = 0; alphabet[i]; i){
for (int j = 0; msgEnc[j]; j){
msgRes[j] = alphabet[(get_letter(msgEnc[j], alphabet) i) % 52];
}
int sameLetters = get_sameletters(msg, msgRes, offset);
if (sameLetters >= max_letters){
max_letters = sameLetters;
distance = i;
}
}
return distance;
}
char *read_Input_Msg(int *msglen)
{//input messages, at the same time counts the length of the entered string
int capacity = INT_MSG_LEN;
char *msg = malloc(capacity);
int c, len = 0;
while ((c = getchar()) != EOF && c != '\n'){
if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))) {
free(msg);
msg = NULL;
len = 0;
break;
}
if (len == capacity){
char *tmp = realloc(msg, capacity * 2);
if (tmp == NULL){
free(msg);
msg = NULL;
len = 0;
break;
}
capacity *= 2;
msg = tmp;
}
msg[len ] = c;
}
*msglen = len;
return msg;
}
char rotate(char *original, int offset)
{
for (int i = 0; i<offset; i){
if (original[i] > 'Z' && original[i]<'a')
original[i] = 6;
else if (original[i] > 'z'){
int k = (int)original[i];
k -= 58;
original[i] = (char)k;
}
}
return *original;
}
When I run it through Valgrind, it says to me that I have errors with the allocated memory, says I do not free it. Writes that memory is not freed at 107.56 and 44 lines, more precisely
==56665== Conditional jump or move depends on uninitialised value(s)
==56665== at 0x4015BF: compare (main.c:107)
==56665== by 0x401468: shift (main.c:56)
==56665== by 0x4012C3: main (main.c:44)
==56665==
�elloword
==56665==
==56665== HEAP SUMMARY:
==56665== in use at exit: 0 bytes in 0 blocks
==56665== total heap usage: 4 allocs, 4 frees, 2,098 bytes allocated
==56665==
==56665== All heap blocks were freed -- no leaks are possible
==56665==
==56665== Use --track-origins=yes to see where uninitialised values come from
==56665== For lists of detected and suppressed errors, rerun with: -s
==56665== ERROR SUMMARY: 52 errors from 1 contexts (suppressed: 0 from 0)
It seems to have freed the memory, but this is not enough, because there is unfreed memory after some function calls. I guess I just don't know how to free it. At the end of each function that asks for additional memory, I tried to free it through free (the array that the function called), but in this case it displays a segmentation fault. I would be grateful if you let me know at least something.
here's example to input
xUbbemehbT
XYlloworld
CodePudding user response:
The valgrind output does not say that you have a memory leak or that you didn't free something properly.
If you look at this part of the output:
==56665== HEAP SUMMARY:
==56665== in use at exit: 0 bytes in 0 blocks
==56665== total heap usage: 4 allocs, 4 frees, 2,098 bytes allocated
==56665==
==56665== All heap blocks were freed -- no leaks are possible
It states that all memory blocks that were allocated were freed. So you don't have an allocation problem.
The important part is this part:
==56665== Conditional jump or move depends on uninitialised value(s)
==56665== at 0x4015BF: compare (main.c:107)
==56665== by 0x401468: shift (main.c:56)
==56665== by 0x4012C3: main (main.c:44)
This says that at the compare
function at line 107 (which was called from shift
at line 56, which in turn was called from main
at line 44), a value that was never initialized was read. This line is:
for (int j = 0; msgEnc[j]; j){
So this tells us you're reading a byte in the msgEnc
array that was never written to. This array was written to in the read_Input_Msg
function which reads one character at a time into the array.
Since this is array is supposed to be a string, and because you're reading a byte at a time, you need to manually add a terminating null byte which you're not doing. So when compare
is eventually called, the above line is looking for a null byte which was never explicitly written, so you end up reading uninitialized bytes.
After the main while
loop in read_Input_Msg
, add the null byte at the end of the string:
while ((c = getchar()) != EOF && c != '\n'){
...
}
msg[len]=0;