如何解决如何将缓冲区[]附加到向量<>然后将其复制到jbytearray?
这会执行 sane_read(使用 SANE)并转换为 Java 应用程序。
expected_bytes
可能不是 100% 准确,因此使用向量。
出了点问题,因为生成的图像是错误的。如果我直接使用 env->SetByteArrayRegion
,它会起作用。
所以,错误出在向量上下文上。
我做错了什么?
long expected_bytes = pars.bytes_per_line * pars.lines *
((pars.format == SANE_FRAME_RGB
|| pars.format == SANE_FRAME_GRAY) ? 1 : 3);
//fprintf (stderr,"Expected bytes: %ld\n",expected_bytes);
SANE_Byte buffer[2048];
SANE_Int bytes_read;
vector<SANE_Byte *> data;
data.reserve(expected_bytes);
do {
status = sane_read((SANE_Handle *)hnd,buffer,sizeof(buffer),&bytes_read);
if (status != SANE_STATUS_GOOD) {
if (status == SANE_STATUS_EOF) {
break;
}
throwEx(env,getError(status));
break;
}
if (bytes_read > 0) {
data.insert(data.end(),&buffer,(&buffer) + bytes_read);
}
}
while(1);
jbyteArray bytes = env->NewByteArray(data.size());
env->SetByteArrayRegion(bytes,data.size(),(const jbyte *) &data[0]);
解决方法
第一个问题是您已将 data
声明为 SANE_Byte*
的向量(即指针)而不是向量 SANE_Byte
(原始字符)。当您调用 SetByteArrayRegion()
时,您希望传入一个指向字符数据的指针,但实际上传入的是一个指向指针数组的指针;那些不会产生所需的图像数据。
第二个问题是您将数据插入向量的方式:
SANE_Byte buffer[2048];
...
data.insert(data.end(),&buffer,(&buffer) + bytes_read);
由于 buffer
的类型为 SANE_Byte[2048]
(2048 字节的数组),这意味着 &buffer
的类型为 SANE_Byte(*)[2048]
(指向 2048 字节的数组的指针)。数组衰减为指向它们的第一个元素的指针,因此在大多数表达式上下文中,buffer
和 &buffer
都具有等效的值,但它们的类型非常不同,并且不会表现出与指针算法一起使用时相同。
假设 buffer
分配在地址 0x01000000。 buffer+1
衰减为 0x01000001,buffer+2047
衰减为数组的最后一个元素 0x010007FF。那里没有惊喜。 &buffer
也是 0x01000000,但如果您考虑表达式 (&buffer) + 1
,则会发生不同的情况:它指向缓冲区开头后 2048 个字节。
这是一个内存图:
Address +0 +1 ... +0x7FF +--------+--------+- -+-----------+ 0x01000000 | buf[0] | buf[1] | ... | buf[2047] | // This row is &buffer +--------+--------+- -+-----------+ 0x01000800 | ? | ? | ... | ? | // This row is (&buffer) + 1 +--------+--------+- -+-----------+ 0x01001000 | ? | ? | ... | ? | // This row is (&buffer) + 2 +--------+--------+- -+-----------+ ... ... +--------+--------+- -+-----------+ 0x013FF800 | ? | ? | ... | ? | // This row is (&buffer) + 2047 +--------+--------+- -+-----------+ 0x01400000 | ? | ? | ... | ? | // This row is (&buffer) + 2048 +--------+--------+- -+-----------+
因此,如果 sane_read()
返回 2048 字节的完整缓冲区,则插入到 [&buffer,(&buffer) + bytes_read)
向量的内存范围是从 {{ 开始的内存区域中读取的 4 MB 字符数据1}},这是一个巨大的缓冲区溢出。然后,对 buffer
的调用将这 4 MB 解释为一个指针数组;如果您在 64 位系统上,那将超过 100 万个指针,其内容未定义。老实说,我很惊讶这没有立即崩溃。
构造向量的正确方法是将其声明为 data.insert()
类型(字符,而不是指针),并在每次循环迭代时将每个缓冲区复制到其中。引用 vector<SANE_Byte>
的正确字节范围的方法不是使用 buffer
到 &buffer
,而是使用 (&buffer) + bytes_read
到 buffer
,或等效地 {{1} }到buffer + bytes_read
:
&buffer[0]
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。