使用 free() 时 C 堆缓冲区损坏

标签 c malloc heap-memory free

释放下面的“shifted_text”时出现以下错误。我已经检查了打印语句并注释掉了内容,它绝对是免费的(shifted_text)。其他免费命令工作正常。

调试错误! 检测到堆损坏:在 0x007D1F 处的正常 block (#77)之后...

CRT 检测到应用程序在堆缓冲区末尾后写入内存。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void parse(int argc, char *argv[]);
char * shift_text(char *sometext);
char shift_letter(char letter, char shift);
void bring_in_text(void);
void write_to_file(char *sometext);

char *flag;
char *password;
char *text;

int main(int argc, char *argv[])
{
    parse(argc, argv);
    char *shifted_text;
    // at this point flag can only be -e, -d, -df, -ef
    if (strcmp(flag, "-e") == 0 || strcmp(flag, "-d") == 0)
    {
        // location to store the shifted text
        shifted_text = (char*)malloc(strlen(text) * sizeof(char));
        shift_text(shifted_text);
        printf("%s\n", shifted_text);
    }
    else
    {
        bring_in_text();
        // location to store the shifted text
        shifted_text = (char*)malloc(strlen(text) * sizeof(char));
        shift_text(shifted_text);
        write_to_file(shifted_text);
    }
    free(shifted_text);
    free(text);
    free(flag);
    free(password);
    return 0;
}

void write_to_file(char *sometext)
{
    if (strcmp(flag, "-df") == 0)
    {
        FILE *fp;
        fp = fopen("plaintext.txt", "w");
        if (fp == NULL)
        {
            puts("Unable to open file");
            exit(1);
        }
        fprintf(fp, sometext);
        fclose(fp);
    }
    else if (strcmp(flag, "-ef") == 0)
    {
        FILE *fp;
        fp = fopen("ciphertext.txt", "w");
        if (fp == NULL)
        {
            puts("Unable to open file");
            exit(1);
        }

        fprintf(fp, sometext);
        fclose(fp);
    }
}

void bring_in_text(void)
{
    if (strcmp(flag, "-df") == 0)
    {       
        FILE *fp;
        fp = fopen("ciphertext.txt", "r");
        if (fp == NULL)
        {
            puts("Unable to open file");
            exit(1);
        }
        while (!feof(fp))
        {
            text = (char*)malloc(100 * sizeof(char));
            fgets(text, 100, fp);
        }
        fclose(fp);
    }
    else if (strcmp(flag, "-ef") == 0)
    {
        FILE *fp;
        fp = fopen("plaintext.txt", "r");
        if (fp == NULL)
        {
            puts("Unable to open file");
            exit(1);
        }
        while (!feof(fp))
        {
            text = (char*)malloc(100 * sizeof(char));
            fgets(text, 100, fp);
        }
        fclose(fp);
    }

}


char * shift_text(char *shifted_text)
{
    char *temptext;
    temptext = text;
    char *tempshiftedtext;
    tempshiftedtext = shifted_text;
    // space for 10 characters plus null
    char *temppswd;
    temppswd = password;

    for (int i = 0; i < strlen(text); i++)
    {
        char a;
        if (*temptext >= 97 && *temptext <= 122)
        {
            a = shift_letter(*(temptext + i), *(temppswd + (i % strlen(password))));
            *(tempshiftedtext + i) = a;
        }
        else
            *(tempshiftedtext + i) = *(temptext + i);
    }
    *(tempshiftedtext + strlen(text)) = '\0';
}

char shift_letter(char letter, char shift)
{
    if (strcmp(flag, "-e") == 0 || strcmp(flag, "-ef") == 0)
    {
        letter = letter - 97;
        shift = shift - 97;
        int shifted_letter = letter + shift;
        if (shifted_letter > 25)
            shifted_letter %= 26;
        shifted_letter += 97;
        return (char)shifted_letter;
    }
    else if (strcmp(flag, "-d") == 0 || strcmp(flag, "-df") == 0)
    {
        int shifted_letter = letter - 97;
        shift = shift - 97;
        int letter = shifted_letter - shift;

        letter %= 26;   // mod seems to allow negative results, so if its still negative. add another val equal to modulus
        if (letter < 0)
            letter += 26;
        letter += 97;
        return (char)letter;
    }
}

void parse(int argc, char *argv[])
{
    if (argc == 4)
    {
        // internally calls malloc on strlen(argv[i])
        flag = _strdup(argv[1]);
        password = _strdup(argv[2]);
        text = _strdup(argv[3]);
        if (strlen(password) > 10)
        {
            puts("Password too long");
            exit(1);
        }
        else if (strcmp(flag, "-e") != 0 && strcmp(flag, "-d") != 0)
        {
            puts("Incorrect flag");
            exit(1);
        }
    }
    else if (argc == 3)
    {
        // internally calls malloc on strlen(argv[i])
        flag = _strdup(argv[1]);
        password = _strdup(argv[2]);
        if (strlen(password) > 10)
        {
            puts("Password too long");
            exit(1);
        }
        else if (strcmp(flag, "-ef") != 0 && strcmp(flag, "-df") != 0)
        {
            puts("Incorrect flag");
            exit(1);
        }
    }
    else
    {
        puts("Incorrect arguements");
        exit(1);
    }
}

函数解析只是将命令行参数存储在全局中。移位函数将字母移位一些数字。例如,“A”移位 2 将是“C”。这些工作正常,没有 free(shifted_text) 程序也可以工作。

我是 C 新手,所以这可能很简单,但我看不到。

最佳答案

改变这个

shifted_text = (char*)malloc(strlen(text) * sizeof(char));

shifted_text = malloc((strlen(text) + 1) * sizeof(char)); // don't cast

C 风格的字符串总是有一个空终止符,表示字符串的结尾。例如,"foo" 在内存中存储为 'f', 'o', 'o', '\0'。所以你必须

我怀疑堆缓冲区损坏不是由您的 free(shifted_text); 引起的。由于分配给 shifted_text 的内存不足,因此会调用未定义的行为,从而使一切成为可能。所以你的程序要么正常运行,要么崩溃。也许这只是巧合,每次注释掉 free(shifted_text); 时,由于未定义的行为,您的程序都会正确运行。

<小时/>

顺便说一句:您的代码中有很多地方需要改进。例如,在 void Bring_in_text(void) 中:

while (!feof(fp))
{
    text = (char*)malloc(100 * sizeof(char));
    fgets(text, 100, fp);
}

覆盖前面的行甚至不处理它们?此外,此函数中不会释放 text

关于使用 free() 时 C 堆缓冲区损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36108813/

相关文章:

c - 此示例导致c4028警告,为什么?

从函数内部更改结构

将 WCHAR 字符串转换为小写 C

c - 如何正确分配结构体和某些变量?

c++ - 在堆栈上分配的变量上调用 delete

c - 即使加载了调试符号,GDB 进入共享库也会显示 "no such file"

C,如何为另一个结构中的结构数组分配正确的空间量?

c++ - 结构中的结构,动态内存分配

java - Spark 应用程序 - Java.lang.OutOfMemoryError : Java heap space

c++ - 分配的内存在栈或堆中