为什么这个缓冲区指向不可寻址的字节?
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 所报告的.
编辑:感谢回复者,我已将 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()
readsnmemb
elements of data, eachsize
bytes long, from the stream pointed to bystream
, storing them at the location given byptr
.
所以,你的代码应该是
while (fread(buffer, sizeof(buffer[0]), 512, file) == 1)
否则,您最终会要求读取和存储 512 个大小为 512 字节的块每个,这是错误的并且会导致缓冲区溢出,如 valgrind 所报告的.