我试图使用JNA从指针中读取一个字节数组,我一直得到:
Decompress with insz 11107, and outsize 65536
recieved 1
Decompression complete!
Decompress with insz 22112, and outsize 65536
recieved 1
Decompression complete!
Decompress with insz 22041, and outsize 65536
recieved 1
Decompression complete, final out size of 0!
Exception in thread "main" java.lang.Error: Invalid memory access
at com.sun.jna.Native.read(Native Method)
at com.sun.jna.Pointer.read(Pointer.java:149)
at com.sun.jna.Pointer.getByteArray(Pointer.java:715)
at me.TTARCHExtract.redo(TTARCHExtract.java:330)
at me.TTARCHExtract.redo(TTARCHExtract.java:323)
at me.TTARCHExtract.z_decompress(TTARCHExtract.java:313)当我执行以下代码时:
public static final Pointer toPointer(byte[] array, int length){
Memory ret = new Memory(length);
ret.write(0, array, 0, length);
return ret;
}
//code starts here
private byte[] z_decompress(byte[] in,int insize,byte[] out,int outsize) {
if(in==null)return null;
System.out.println("Decompress with insz "+insize+", and outsize "+outsize);
Pointer inptr = toPointer(in, insize);
Pointer outptr = toPointer(out, outsize);
ZStream deflate = new ZStream();
ZStream z = new ZStream();
TTARCHHelper.load();
ZlibLibrary lib = TTARCHHelper.ZLIB_LIBRARY;
this.initz(lib, z, 15);
this.initz(lib, deflate, -15);
return this.redo(insize, outsize, z, lib, inptr, outptr, true, deflate);
}
private byte[] redo(int insize,int outsize,ZStream z,ZlibLibrary lib,Pointer inptr,Pointer outptr,boolean first,ZStream deflate) {
lib.inflateReset(z);
z.next_in=inptr;
z.next_out=outptr;
z.avail_in=insize;
z.avail_out=outsize;
int out = lib.inflate(z, ZlibLibrary.Z_FINISH);
if(!first)System.out.println("recieved "+out);
if(out != ZlibLibrary.Z_STREAM_END) {
if(first)return this.redo(insize, outsize, deflate, lib, inptr, outptr, false, null);
System.out.println("Compressed zlib/deflate input at offset "
+ ""+dgboff+" ("+insize+" > "+outsize+") is wrong or complete");
System.exit(-1);
return null;
}
System.out.println("Decompression complete!");
return z.next_out.getByteArray(0, outsize);
}
private void initz(ZlibLibrary lib,ZStream z, int w) {
lib.inflateInit2_(z, w, lib.zlibVersion(), z.size());
}getByteArray是错误发生的地方。是什么导致了这一切?
这个错误有时会发生,并不是所有的zlib输入流都会发生,所以这与out的大小可能是错误的吗?
代码来自C编写的项目交图文
发布于 2020-08-27 23:16:02
JNA中的Invalid Memory Access错误表明您正在尝试访问尚未分配的内存。在这种情况下,next_out指针具有完整的outsize长度。要调试这一点,您需要参考API,查看函数是否希望您分配内存并将其传递给本机函数,或者本机函数本身是否将分配必要的内存。(在后一种情况下,本机代码通常告诉您如何在完成内存时释放内存。)对于这个API,分配显然是在inflateInit2()调用中完成的,因此这是对bug根源的提示。
输出很有启发性,因为它表明它在一个较小的insz中成功了一次,但是第二次在较大的insz中失败了。这种差异在崩溃的堆栈跟踪中也很明显,显示递归调用发生在第二次(更大的输入)情况下,但在第一种情况下可能没有。(要在调试中确认这一点,您应该添加更多的输出。)
对于递归调用,唯一的更改是,第三个参数将被更改为ZStream z,而不是Zstream deflate (其中null作为迭代中可能的下一个值传递)。虽然将z更改为deflate似乎是正确的,但我看不出原始代码中应该有一个null。这似乎是打算递归作为一个“下一个”类型的迭代,直到它完成。(这可能不是造成错误的原因,但很可疑。)
redo()调用与deflate参数(而不是z )之间的唯一区别是,调用deflate的窗口大小为-15。这似乎与您映射的文档 for inflateInit2_()背道而驰:
windowBits参数应该是要使用的最大窗口大小的基数2对数,并且应该是8到15之间的值。
由于您正在移植的原始C代码也使用了-15,这可能是正确的,但很明显,不同的窗口大小会对输出产生影响。
我建议将deflate保留为递归调用的最后一个参数,而不是null,并添加更多的输出语句,以便在递归过程中更深入地了解参数的值。
另一个可能导致错误的变量是outsize值。这似乎意味着可以读取完整的outsize值,如果您已经到达分配的末尾,则情况可能不是这样。可能outsize是一个最小的大小(可能是windowsize = 15导致这是真的),但是当递归( windowsize = -15大小写)不能依赖时,您应该在最后一次迭代时从输出中读取更少的字节(查看原始源会提示z.total_out)。
https://stackoverflow.com/questions/63624246
复制相似问题