为什么遍历十六进制数组会提前停止?

Why does iterating over a hex array stop early?

问题和代码

我正在使用代码在 Raspberry Pi 上截取屏幕截图。使用 VC 处理程序的一些魔法,我可以截取屏幕截图并使用 calloc 将其存储在内存中。我可以使用它来将数据作为 ppm 图像存储在文件中,其中包含必要的 header 使用:

void * image;
image = calloc(1, width * 3 * height);
// code to store data into *image
FILE *fp = fopen("myfile.ppm", "wb");
fprintf(fp, "P6\n%d %d\n255\n", width, height);
fwrite(image, width*3*height, 1, fp);
fclose(fp);

这样就成功存储了数据。我可以正常访问和查看。

但是,如果我改为尝试通过打印来检查为了调试目的而放入文件中的数据:

int cnt = 0;
std::string imstr = (char *)image;
for (int i=0; i<(width*3*height); i++) {
    std::cout << (int)imstr[i] << "  " << cnt << std::endl;
    cnt += 1;
    }

segfault早。打印中返回的数字对上下文有意义(例如颜色值 <255)

示例编号

在 1280 x 768 x 3 图像的情况下,我的 cnt 停止在 64231。它停止的值似乎与 sizeof [=17] 没有任何关系=] 或 int.

我想我在这里遗漏了一些明显的东西,但我看不到。有什么建议吗?

很可能你在 (char *)image 中至少有一个空字符,所以 std::string 长度比 width*3*height 短,因为它的初始化是因为只有第一个空字符之前的字符使用字符

使用 std::array 而不是像那样初始化的 std::string

您将 image 数据转换为 std::string 的方式是错误的。如果 image 的原始数据包含任何 0x00 字节,那么 std::string 将被截断,导致您的循环访问超出 std::string 的范围。如果 image 的原始数据不包含任何 0x00 字节,那么 std::string 构造函数将尝试读取超出 image 分配内存的边界。

构造std::string时需要考虑image的大小,例如:

size_t cnt = 0;
std::string imstr(static_cast<char*>(image), width*3*height);
for (size_t i = 0; i < imstr.size(); ++i) {
    std::cout << static_cast<int>(imstr[i]) << "  " << cnt << std::endl;
    ++cnt;
}

否则,根本不要将 image 转换为 std::string。您可以直接迭代 image 的原始数据,例如:

size_t cnt = 0, imsize = width*3*height;
char *imdata = static_cast<char*>(image);
for (size_t i = 0; i < imsize; ++i) {
    std::cout << static_cast<int>(imdata[i]) << "  " << cnt << std::endl;
    ++cnt;
}