Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在JNI库中调用memcpy()执行USB i/o时发生访问冲突_Java_C_Java Native Interface - Fatal编程技术网

Java 在JNI库中调用memcpy()执行USB i/o时发生访问冲突

Java 在JNI库中调用memcpy()执行USB i/o时发生访问冲突,java,c,java-native-interface,Java,C,Java Native Interface,我正在编写一个Java应用程序,它使用Java10JDK在Windows10上执行USB I/O。我的i/o库是libusb api。应用程序加载JNI库。DLL在Visual Studio 2017中编译,微软Visual C++ 2013和微软Visual C++ 2015-2019都安装了。当在Netbeans 11.1项目中运行时,此应用程序会生成以下崩溃警告 pc=0x000002e1bbcd122e、pid=444、tid=3244时的异常访问违反(0xc0000005) JRE版本

我正在编写一个Java应用程序,它使用Java10JDK在Windows10上执行USB I/O。我的i/o库是libusb api。应用程序加载JNI库。DLL在Visual Studio 2017中编译,微软Visual C++ 2013和微软Visual C++ 2015-2019都安装了。当在Netbeans 11.1项目中运行时,此应用程序会生成以下崩溃警告

pc=0x000002e1bbcd122e、pid=444、tid=3244时的异常访问违反(0xc0000005)
JRE版本:Java(TM)SE运行时环境(10.0+46)(构建10+46) Java虚拟机:Java热点(TM)64位服务器虚拟机(10+46,混合模式,分层,压缩oops,g1 gc,windows-amd64)

问题帧:
C[VCRUNTIME140D.dll+0x122e]

问题函数是VisualStudio build.dll中C代码中的我的USB读取函数

JNI.c

JNIEXPORT jint JNICALL Java\u SWMAPI\u iosb\u read
(JNIEnv*env,jobject thisObj,jbyteArray jArr,jint size,jlong javaHandle){
//将jLong转换为设备句柄指针
libusb_设备_句柄*句柄=(libusb_设备_句柄*)javaHandle;
//jbyteArray jArr:byte[]缓冲区。必须用从具有的设备读取的USB数据覆盖
//对应的句柄javaHandle。
//jlong javaHandle:从表示设备的java长时间传递到I/O。
//jint size:jArr长度(例如buffer.length),用于调试。
int status;//返回代码值
int字节(已写入);;
读取整数字节;
MESSAGE MESSAGE;//包含9字节消息头和(n)字节有效负载的C结构。
int-length=(*env)->GetArrayLength(env,jArr);
jbyte*bufferIn=(*env)->GetPrimitiveArrayCritical(env,jArr,NULL);//从jArr获取内存
//将bufferIn中的数据复制到消息结构。
memcpy((unsigned char*)和Message(unsigned char*)bufferIn,长度);
//将消息写入设备
字节写入=libusb控制传输(句柄、CTRL\u输出、MEM\u RQ、0、0、(无符号字符*)&消息、长度、0);
if(字节\写入==长度){
//从设备读取数据到消息(&M)
字节读取=libusb控制传输(句柄,CTRL输入,内存RQ,0,0,(无符号字符
*)&消息,sizeof(消息),30000);
状态=(字节写入<0)?字节读取://I/O错误
(字节写入<长度)?USB\u状态\u短写://检查短写
Libus_成功;
如果(Message.payload.length>=0){//如果读取数据>0
printf(“尝试memcpy\n”);
fflush(stdout);
//错误出现在下面的行中
memcpy((unsigned char*)bufferIn,(unsigned char*)和Message,最大页眉长度+
消息。有效载荷。长度);
printf(“Success memcpy\n”);
fflush(stdout);
}
}
(*env)->ReleasePrimitiveArrayCritical(env,jArr,bufferIn,0);
返回状态;
}

到今天为止,这个函数一直在为我的项目工作。其频率约为3次运行中的1次。有人能告诉我如何解决这个问题吗

说memcpy是Windows机器上的禁用函数安全吗?为什么要问
memcpy()
是否是“禁用函数”?“长度”来自哪里?该函数是通过
jint size
,而不是
length
@AndrewHenle传递的。我只是想知道Windows是否会尝试控制某些被认为太不安全的函数。我忘了长度的代码了。它现在就在那里。明显的问题时间:什么是
sizeof(MESSAGE)
,什么是
length
,什么是
MAX\u HEADER\u length+MESSAGE.payload.length
?另外,您是否验证了
bufferIn
不是空指针?此外,有效负载是否完全包含在
消息中,还是在消息之后,因为您只将
sizeof(MESSAGE)
字节从USB读取到
消息中,但尝试
memcpy
更多。@idoteque90 Microsoft声称
memcpy()
strcpy()
等函数是错误的,这是在欺骗您“已弃用”。它们只是被Microsoft“弃用”,愤世嫉俗者会说这是为了“帮助”编写特定于Microsoft的代码,使移植到另一个平台变得更困难。请参阅“由于与规范的大量偏差,Microsoft实现不能被视为符合或可移植。”
JNIEXPORT jint JNICALL Java_SWMAPI_IoUSB_read
(JNIEnv * env, jobject thisObj, jbyteArray jArr, jint size, jlong javaHandle){   

    //Convert jLong to device handle pointer
    libusb_device_handle * handle = (libusb_device_handle * )javaHandle;

    //jbyteArray jArr: byte [] buffer.  Must be overwritten with USB read data from device with 
    //                                  corresponding handle javaHandle.
    //jlong javaHandle:  long passed from java representing the device to I/O.
    //jint size:         jArr length (e.g. buffer.length), used for debugging.

    int status;         //return code value
    int bytes_written;
    int bytes_read;

    MESSAGE Message;    //C struct containing 9 bytes of message header and (n) bytes of payload.

    int length = (*env)->GetArrayLength(env, jArr);

    jbyte * bufferIn = (*env)->GetPrimitiveArrayCritical(env, jArr, NULL);  //get memory from jArr

    //copy data in bufferIn to a Message struct.
    memcpy((unsigned char *)&Message, (unsigned char *)bufferIn, length);  

    //write the Message out to device
    bytes_written = libusb_control_transfer(handle, CTRL_OUT, MEM_RQ, 0, 0, (unsigned char *)&Message, length, 0);

    if(bytes_written == length){
        //read data in from Device to &Message
        bytes_read = libusb_control_transfer(handle, CTRL_IN, MEM_RQ, 0, 0, (unsigned char 
        *)&Message, sizeof(MESSAGE), 30000);

        status = (bytes_written < 0) ? bytes_read :                 // I/O Error
            (bytes_written < length) ? USB_STATUS_SHORT_WRITE :     // Check for short write
            LIBUSB_SUCCESS;
        if(Message.payload.length >= 0){                            //If read data > 0
            printf("Attempting memcpy\n");
            fflush(stdout);

            // The error appears on the line below
            memcpy((unsigned char *)bufferIn,(unsigned char *)&Message, MAX_HEADER_LENGTH + 
            Message.payload.length);

            printf("Success memcpy\n");
            fflush(stdout);
        }
    }

    (*env)->ReleasePrimitiveArrayCritical(env, jArr, bufferIn, 0);
    return status;
}