如何正确释放内存?

发布于 2025-01-17 05:22:36 字数 5498 浏览 4 评论 0原文

请帮忙,我不知道如何正确释放内存。下面有一段代码

#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;
}

当我通过 Valgrind 运行它时,它告诉我分配的内存有错误,说我没有释放它。在107.56和44行写到内存没有释放,更准确地说

==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)

看起来已经释放了内存,但这还不够,因为在一些函数调用之后还有未释放的内存。我想我只是不知道如何释放它。在每个请求额外内存的函数末尾,我尝试通过 free (函数调用的数组)释放它,但在这种情况下它显示分段错误。如果您至少让我知道一些信息,我将不胜感激。

这是输入的示例

xUbbemehbT
XYlloworld

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

酸甜透明夹心 2025-01-24 05:22:36

valgrind 输出不会表明您存在内存泄漏或没有正确释放某些内容。

如果您查看这部分输出:

==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== 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)

这表示在第 107 行的 compare 函数(该函数是从第 56 行的 shift 调用的,而该函数又是从 main 在第 44 行),读取了一个从未初始化的值。这一行是:

for (int j = 0; msgEnc[j]; ++j){

所以这告诉我们您正在读取 msgEnc 数组中的一个从未写入过的字节。该数组是在 read_Input_Msg 函数中写入的,该函数一次将一个字符读入数组中。

由于这是数组应该是一个字符串,并且因为您一次读取一个字节,所以您需要手动添加一个您没有执行的终止空字节。因此,当最终调用 compare 时,上面的行将查找从未显式写入的空字节,因此您最终会读取未初始化的字节。

read_Input_Msg 中的主 while 循环之后,在字符串末尾添加空字节:

while ((c = getchar()) != EOF && c != '\n'){
    ...
}
msg[len]=0;

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文