c - "Invalid write of size 1"和指针具有正确的内存地址,但仍然会抛出错误

标签 c memory-management valgrind free

下面的代码给了我 2 个错误 - 大小 1 的无效写入地址 0x41f52a8 在大小为 128 的 block 分配后是 0 个字节。下面是完整的 valgrind 堆栈。

我可以进行猜测并确定 memcpy(content2 +totalLength + 1, fileContentTemp, readBytes); 代码行有问题。因此,我将其更正为 memcpy(content2 +totalLength, fileContentTemp, readBytes); 然后我的 valgrind 变得非常高兴,一切都通过了。

但我无法理解其中的原因。对我来说,从第二次开始,我需要执行 + 1 因为我不希望 memcpycontent2 + totalLength 地址开始写入因为它是写入最后一个字节的地址,所以我想增加并从下一个地址开始。

另外,另一个有趣的部分是,如果我不纠正它,我会收到以下运行时错误 *** ./server_issue' 中的错误:双重释放或损坏 (!prev): 0x08c24170 ***,我猜是因为这行代码 free(content2);free 基本上释放了指针,现在如果指针具有正确的内存地址(我验证了 content2 具有正确的内存地址)那么为什么会发生异常。

代码:

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

typedef char BYTE;
bool load(FILE*, BYTE**, size_t*);

int main(void) {
    FILE *file = fopen("/home/jharvard/psets/pset6/pset6_working/public/hello.html", "r");
    BYTE *content;
    size_t length;
    load(file, &content, &length);
}

bool load(FILE *file, BYTE **content, size_t *length) {
    //printf("file %p\n", file);

    int totalLength = 0;
    int readBytes = 0;
    BYTE *content2 = NULL;

    BYTE *fileContentTemp[64]; // working with 222222
    while ((readBytes = fread(fileContentTemp, 1, 64, file)) > 0) {
        printf("Reallocating %d bytes, ", readBytes);
        content2 = realloc(content2, sizeof(BYTE) * (totalLength + readBytes));

        printf("%p\n", content2);
        if (totalLength != 0) {
            memcpy(content2 + totalLength + 1, fileContentTemp, readBytes);        
        } else {
            memcpy(content2 + totalLength, fileContentTemp, readBytes);        
        }
        totalLength = totalLength + readBytes;
    }

    *length = totalLength;
    *content = content2;

    free(content2);

    //printf("CC image: %s\n", *content);
    //printf("length is %d\n", *length);
    //printf("fileContent %p\n", *content);
    //printf("file %p\n", file);

    fclose(file);

    //printf("length is %d\n", *length);

    return true;
}

Valgrind 堆栈:

appliance (~/psets/pset6/pset6_working): valgrind ./server_issue
==3206== Memcheck, a memory error detector
==3206== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==3206== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==3206== Command: ./server_issue
==3206== 
Reallocating 64 bytes, 0x41f51b8
Reallocating 64 bytes, 0x41f5228
==3206== Invalid write of size 1
==3206==    at 0x402F04B: memcpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3206==    by 0x80486AC: load (in /home/jharvard/psets/pset6/pset6_working/server_issue)
==3206==    by 0x8048599: main (in /home/jharvard/psets/pset6/pset6_working/server_issue)
==3206==  Address 0x41f52a8 is 0 bytes after a block of size 128 alloc'd
==3206==    at 0x402C324: realloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3206==    by 0x804865C: load (in /home/jharvard/psets/pset6/pset6_working/server_issue)
==3206==    by 0x8048599: main (in /home/jharvard/psets/pset6/pset6_working/server_issue)
==3206== 
Reallocating 64 bytes, 0x41f52d8
Reallocating 64 bytes, 0x41f53c8
Reallocating 60 bytes, 0x41f54f8
==3206== 
==3206== HEAP SUMMARY:
==3206==     in use at exit: 0 bytes in 0 blocks
==3206==   total heap usage: 6 allocs, 6 frees, 1,308 bytes allocated
==3206== 
==3206== All heap blocks were freed -- no leaks are possible
==3206== 
==3206== For counts of detected and suppressed errors, rerun with: -v
==3206== ERROR SUMMARY: 4 errors from 1 contexts (suppressed: 0 from 0)

最佳答案

这归结为以下事实:前 N 个整数的列表从 0 开始,到 N-1 结束。

让我们尝试一个具体的例子。假设您从索引 0 写入 4 个字节。您写入索引 0、1、2 和 3。总共 4 个字节。所以右边的下一个是索引 4,而不是 5。

假设您从索引 M 写入 N 个字节。您写入 M、M+1、...、M+N-1。你写的下一个是M+N。

因此将整个 if 语句替换为

memcpy(content2 + totalLength, fileContentTemp, readBytes); 

if 应该感觉不对。像这样的操作不需要特殊的大小写,因此您有一个 if 的事实应该引起警钟。

关于c - "Invalid write of size 1"和指针具有正确的内存地址,但仍然会抛出错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35879470/

相关文章:

c - C , linux 中的音频视频编程

mysql - 如何为所有浏览器存储无限量的 cookie 条目

macos - Java 问题 : Memory and CPU usage in MAC OS

c++ - 使用 Valgrind 检测内存泄漏

c - 如何确定 valgrind 中哪些值未初始化?

c++ - Valgrind 错误读取大小为 4 无效

c - 整数比较失败

c - 查找最大人口和 C 中的最大世代,包括指针

c - pb用C程序: double free or corruption (! prev)

c - 自动与动态内存分配 : what to consider?