C语言 尝试释放堆分配内存时出错

t0ybt7op  于 2022-12-02  发布在  其他
关注(0)|答案(1)|浏览(157)

我正在开发一个程序,它可以从输入文件中逐行读取文本。一旦读取了该行,程序就会颠倒该字符串中单词的顺序,将其打印到输出文件中,然后开始阅读下一行。我的程序只从一行中读取特定数量的字符,这意味着如果一行包含的字符多于该特定数量,所有这些都必须跳过,直到到达下一行。我的程序似乎工作得很好。
任务要求之一是使用动态分配的数组。这是我的主要问题所在。一旦我试图释放堆分配的内存,程序失败并显示错误消息:检测到堆损坏。一定是我在与他们合作时搞砸了什么。但我无法找到真实的的原因。

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

#define BUFFER_SIZE 255

int readLine(FILE** stream, char** buffer, int* bufferSize);
void reverseString(char* buffer, char** reverse, int bufferSize, int lastLine);

int main(int argc, char** argv)
{
    char* buffer = NULL;
    char* reverse = NULL;
    int bufferSize = 0;
    int lastLine = 0;

    FILE* intputStream = fopen(argv[1], "r");
    FILE* outputStream = fopen(argv[2], "w");

    if (intputStream == NULL || outputStream == NULL)
    {
        printf("Input or output file cannot be opened\n");
        return 0;
    }

    while (!feof(intputStream))
    {
        lastLine = readLine(&intputStream, &buffer, &bufferSize);

        reverse = (char*)malloc(sizeof(char) * bufferSize);
        if (reverse != NULL)
        {
            reverseString(buffer, &reverse, bufferSize, lastLine);
            fputs(reverse, outputStream);
        }

    }

    fclose(intputStream);
    fclose(outputStream);

    free(buffer);
    free(reverse);

    return 0;
}

int readLine(FILE** stream, char** buffer, int* bufferSize)
{
    char tempBuffer[BUFFER_SIZE] = { 0 };
    int lastLine = 0;

    if (*stream != NULL)
    {
        fgets(tempBuffer, BUFFER_SIZE, *stream);
        char ignoredChar[100] = { 0 };

        *bufferSize = strlen(tempBuffer);
        // Ignoring in the same line left characters and checking if this is the last line
        if (tempBuffer[(*bufferSize) - 1] != '\n')
        {
            fgets(ignoredChar, 100, *stream);
            if (!feof(*stream))
                lastLine = 1;
        }
        // Allocating memory and copying line to dynamically-allocated array
        *buffer = (char*)malloc(sizeof(char) * (*bufferSize));
        if (*buffer != NULL)
        {
            memcpy(*buffer, tempBuffer, (*bufferSize));
            (*buffer)[(*bufferSize)] = '\0';
        }
    }
    // Return whether or not the last line is read
    return lastLine;
}

void reverseString(char* buffer, char** reverse, int bufferSize, int lastLine)
{
    int startingValue = (lastLine ? bufferSize - 1 : bufferSize - 2);
    int wordStart = startingValue, wordEnd = startingValue;
    int index = 0;

    while (wordStart > 0)
    {
        if (buffer[wordStart] == ' ')
        {
            int i = wordStart + 1;
            while (i <= wordEnd)
                (*reverse)[index++] = buffer[i++];
            (*reverse)[index++] = ' ';
            wordEnd = wordStart - 1;
        }
        wordStart--;
    }

    for (int i = 0; i <= wordEnd; i++)
    {
        (*reverse)[index] = buffer[i];
        index++;
    }

    if (!lastLine)
        (*reverse)[index++] = '\n';
    (*reverse)[index] = '\0';
}
xlpyo6sf

xlpyo6sf1#

***其中一个***问题是在readLine中,您像这样分配和复制字符串(代码缩短为相关部分):

*bufferSize = strlen(tempBuffer);
*buffer = (char*)malloc(sizeof(char) * (*bufferSize));
(*buffer)[(*bufferSize)] = '\0';

这将 * 不 * 为空值终止符分配空间。并且您将写入空值终止符 * 超出 * 分配的内存。这将导致 * 未定义的行为 *。
您需要为空终止符分配一个额外的字节:

*buffer = malloc(*bufferSize + 1);  // +1 for null-terminator

[Note I don't cast the result,不要使用sizeof(char),因为它被指定为 * 始终 * 等于1。]

***另一个***问题是,由于您没有在bufferSize中包含空终止符,因此mainreverse的分配也将是错误的:

reverse = (char*)malloc(sizeof(char) * bufferSize);

当然应该改为:

reverse = malloc(bufferSize + 1);  // +1 for null-terminator

相关问题