Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C &引用;大小为“1”的写入无效;指针有正确的内存地址,但仍然会抛出错误_C_Memory Management_Valgrind_Free - Fatal编程技术网

C &引用;大小为“1”的写入无效;指针有正确的内存地址,但仍然会抛出错误

C &引用;大小为“1”的写入无效;指针有正确的内存地址,但仍然会抛出错误,c,memory-management,valgrind,free,C,Memory Management,Valgrind,Free,下面的代码给了我2个错误-大小为1的无效写入,地址0x41f52a8在分配大小为128的块后为0字节。下面是完整的valgrind堆栈 我可以做一个猜测工作并确定memcpy(content2+totalLength+1,fileContentTemp,readBytes)代码行有问题。因此,我将其更正为memcpy(content2+totalLength,fileContentTemp,readBytes)

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

我可以做一个猜测工作并确定
memcpy(content2+totalLength+1,fileContentTemp,readBytes)代码行有问题。因此,我将其更正为
memcpy(content2+totalLength,fileContentTemp,readBytes)
但我无法理解原因。对我来说,从第二次开始,我需要做
+1
,因为我不希望
memcpy
content2+totalLength
地址开始写入,因为它是最后一个字节写入的地址,所以我想从下一个地址开始递增

另外,另一个有趣的部分是,如果我不纠正它,那么我会在./server_issue中得到以下运行时错误
***错误:双重免费或损坏(!prev):0x08c24170***
,我猜是因为这行代码
免费(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;
}
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
的事实应该会引起警钟

谢谢你的意见。我想了想,但后来-假设我的第一个内存位置是0x100,我写了4个字节,所以最后一个字节写在0x103。现在,当我说
memcpy(content2+totalLength,fileContentTemp,readBytes)
那么这意味着我的内存地址将变成
content2
即0x100+
totalLength
即4,因此等于0x103。这就是我怀疑memcpy是否会从0x103开始写的地方,所以我做了
+1
。呃,这不是如何将4添加到0x100。0x100+4是0x104。哦,我很惭愧,我真傻!我应用了逻辑,我有4个字节要写,我从0x100开始,所以我将以0x103结束(这是真的),但这是简单的数学,不是关于写字节。对于./server_issue中的
***错误:双重释放或损坏(!prev):0x08c24170***
您认为这是因为
memcpy
的内存损坏吗?是的,您损坏了堆,然后可能会发生任何事情