为什么这个缓冲区指向不可寻址的字节?

Why does this buffer point to unaddressable bytes?

编辑:感谢回复者,我已将 fread 更改为 (...sizeof buffer, 1,...),但现在我在 valgrind 中收到此错误:

==2409== Invalid read of size 4
==2409==    at 0x51AB8D0: fread (iofread.c:41)
==2409==    by 0x4007B6: main (recover2.c:31)
==2409==  Address 0x5502000 is not stack'd, malloc'd or (recently) free'd
==2409== 
==2409== Use of uninitialised value of size 8
==2409==    at 0x51B8787: _IO_sgetn (genops.c:495)
==2409==    by 0x51AB93E: fread (iofread.c:42)
==2409==    by 0x4007B6: main (recover2.c:31)
==2409== 
==2409== Invalid read of size 8
==2409==    at 0x51B8787: _IO_sgetn (genops.c:495)
==2409==    by 0x51AB93E: fread (iofread.c:42)
==2409==    by 0x4007B6: main (recover2.c:31)
==2409==  Address 0x40 is not stack'd, malloc'd or (recently) free'd
==2409== 
==2409== 
==2409== Process terminating with default action of signal 11 (SIGSEGV)
==2409==  Access not within mapped region at address 0x40
==2409==    at 0x51B8787: _IO_sgetn (genops.c:495)
==2409==    by 0x51AB93E: fread (iofread.c:42)
==2409==    by 0x4007B6: main (recover2.c:31)
==2409==  If you believe this happened as a result of a stack
==2409==  overflow in your program's main thread (unlikely but
==2409==  possible), you can try to increase the size of the
==2409==  main thread stack using the --main-stacksize= flag.
==2409==  The main thread stack size used in this run was 8388608.

我是新来的,所以我希望这是有道理的。我正在编写此代码以从文件中检索数据并将其复制到 jpeg 文件中。该代码旨在通过 header 找到一个 jpg 文件,然后将其写入文件。代码是:

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

int main(int argc, char* argv[])
{

FILE* file = fopen("card.raw", "r");
if (file == NULL)
{ 
    printf("Could not open file!\n");
    return 1;
}

char title[7];
int currentImage = 0;
uint8_t buffer[512];
FILE* img;
while (fread(buffer, sizeof(buffer), 512, file) == 1)
{
printf("found data!\n");
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff)
{
    if (buffer[3] == 0xe0 || buffer[3] == 0xe1 || buffer[3] == 0xe2 || buffer[3] == 0xe3 || buffer[3] == 0xe4 || buffer[3] == 0xe5 || buffer[3] == 0xe6 || buffer[3] == 0xe7 || buffer[3] == 0xe8 || buffer[3] == 0xe9 || buffer[3] == 0xea || buffer[3] == 0xeb || buffer[3] == 0xec || buffer[3] == 0xed || buffer[3] == 0xee || buffer[3] == 0xef)
    {
        printf("Found new jpg!\n");
        sprintf(title, "%03d.jpg", currentImage);
        img = fopen(title, "a");
        currentImage++;
        printf("size of buffer to print is %lu\n", sizeof(buffer));
        fwrite(buffer, sizeof(buffer), 1, img);
        }
}
else if (currentImage > 0)
{ 
        fwrite(buffer, sizeof(buffer), 1, img);


}

}
}

一旦找到 jpeg 并执行 fwrite,然后 returns 到 while 循环,我就会遇到分段错误。

valgrind 错误是:

==1866== Syscall param read(buf) points to unaddressable byte(s)
==1866==    at 0x5228810: __read_nocancel (syscall-template.S:81)
==1866==    by 0x51B63B8: _IO_file_xsgetn (fileops.c:1438)
==1866==    by 0x51AB93E: fread (iofread.c:42)
==1866==    by 0x4007C3: main (recover2.c:31)
==1866==  Address 0xfff001000 is not stack'd, malloc'd or (recently) free'd
==1866== 
==1866== Jump to the invalid address stated on the next line
==1866==    at 0x0: ???
==1866==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==1866== 
==1866== 
==1866== Process terminating with default action of signal 11 (SIGSEGV)
==1866==  Bad permissions for mapped region at address 0x0
==1866==    at 0x0: ???

我是新手,所以仍在学习内存等知识,所以如果能帮助我理解为什么会出错,我们将不胜感激。

通过这样做

fread(buffer, sizeof(buffer), 512, file)

您要求 fread 读取 512 个块,每个块的长度为 sizeof(buffer) 字节。 IE。您正在尝试将 512*512 = 262144 字节读入声明为 uint8_t buffer[512] 的数组中。那肯定不合适。

如果您只是想将数据读入 buffer 数组,可以是

fread(buffer, sizeof buffer, 1, file)

fread(buffer, 1, sizeof buffer, file)

或者,如果您愿意,

fread(buffer, sizeof *buffer, sizeof buffer / sizeof *buffer, file)

取决于您在读取操作中对 "atomic" 数据块的看法。


还有

sprintf(title, "%03d.jpg", currentImage);

将生成至少 7 个字符长的字符串(例如 001.jpg),这意味着 title 必须至少有 8 个字符长才能容纳零终止符。但是,您的 title 被声明为

char title[7];

这个太小了。

根据fread()man page,签名是

size_t fread(void *ptr, size_t size, size_t nmemb, FILE * stream );

描述在哪里

The function fread() reads nmemb elements of data, each size bytes long, from the stream pointed to by stream, storing them at the location given by ptr.

所以,你的代码应该是

 while (fread(buffer, sizeof(buffer[0]), 512, file) == 1)

否则,您最终会要求读取和存储 512 个大小为 512 字节的块每个,这是错误的并且会导致缓冲区溢出,如 valgrind 所报告的.