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

时间:2016-03-20 00:13:27

标签: c malloc heap free

我在下面释放“shifted_text”时遇到以下错误。我已经检查过print语句并对事情进行评论,这肯定是免费的(shifted_text)。其他免费命令工作正常。

调试错误! HEAP CORRUPTION DETECTED:正常阻止(#77)0x007D1F ...

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'。这些工作正常,没有程序可用的免费(shifted_text)。

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

2 个答案:

答案 0 :(得分:1)

更改此

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);被注释掉,由于未定义的行为,你的程序运行正常。

BTW:您的代码中有许多地方需要改进。例如,在void bring_in_text(void)

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

覆盖以前的行甚至没有处理它们?此外,此函数中未释放text

答案 1 :(得分:0)

strdup分配strlen + 1个字符,你只分配strlen字符。当您在移位文本的末尾写入null时,您将溢出缓冲区。