JNA: __stdcall ESP corruption
JNA: __stdcall ESP corruption
当我试图通过JNA回调从C++应用程序获得通知时,我经常看到JVM崩溃。Native.setProtected没有帮助。原始回调声明是
typedef void (__stdcall *TRANS2QUIK_ORDER_STATUS_CALLBACK) (long nMode, DWORD dwTransID, double dNumber, LPCSTR ClassCode, LPCSTR SecCode, double dPrice, long nBalance, double dValue, long nIsSell, long nStatus, long nOrderDescriptor);
^^^这是不起作用的
我尝试了StdCallLibrary.StdCallback(应该可以工作)和简单回调,但都失败了。但在我编写了C++包装器之后,我只是从原始C++stdcall回调内部将JNA回调调用为cdecl,一切都开始顺利工作。
typedef void (*WRAPPED_ORDER_STATUS_CALLBACK) (double dNumber, double dPrice, long nBalance, double dValue, long nIsSell, long nStatus, long nOrderDescriptor);
QUIKWRAP_API TRANS2QUIK_ORDER_STATUS_CALLBACK __stdcall wrapCallback(WRAPPED_ORDER_STATUS_CALLBACK);
这是在没有问题的情况下顺利工作的
问题是,这可能是专门针对该函数签名的JNA错误吗?因为我的代码中有另一个具有不同签名的stdcall回调,它运行得很好。
我为这个问题创建了一个独立的测试用例,请参阅下面的:java
import java.util.HashMap;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.PointerType;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.win32.StdCallLibrary;
public class JNATest {
interface TestCallback extends StdCallLibrary.StdCallCallback {
void testCallback(NativeLong nMode, WinDef.DWORD dwTransID, double dNumber, LPCSTR ClassCode, LPCSTR SecCode, double dPrice, NativeLong nBalance, double dValue, NativeLong nIsSell, NativeLong nStatus, NativeLong nOrderDescriptor);
}
interface JNADLL extends StdCallLibrary{
void testCallback(TestCallback cb);
}
public static class LPCSTR extends PointerType {
public LPCSTR(Pointer address) {
super(address);
}
public LPCSTR() {
super();
}
@Override
public String toString() {
return getPointer().getString(0);
}
};
/**
* @param args
*/
public static void main(String[] args) {
System.setProperty("jna.encoding", "Cp1251");
HashMap<String, Object> nameMapping = new HashMap<String, Object>();
nameMapping.put(Library.OPTION_FUNCTION_MAPPER, StdCallLibrary.FUNCTION_MAPPER);
nameMapping.put(Library.OPTION_CALLING_CONVENTION, StdCallLibrary.STDCALL_CONVENTION);
JNADLL JNADll = (JNADLL) Native.loadLibrary("QuikWrap", JNADLL.class, nameMapping);
TestCallback cb = new TestCallback() {
@Override
public void testCallback(NativeLong nMode, DWORD dwTransID,
double dNumber, JNATest.LPCSTR ClassCode, JNATest.LPCSTR SecCode,
double dPrice, NativeLong nBalance, double dValue,
NativeLong nIsSell, NativeLong nStatus, NativeLong nOrderDescriptor) {
System.out.println("testCallback n" +
" nMode: " + nMode + "n" +
" dwTransID: " + dwTransID + "n" +
" number: " + dNumber + "n" +
" ClassCode: " + ClassCode + "n" +
" SecCode: " + SecCode + "n" +
" price: " + dPrice + "n" +
" balance: " + nBalance + "n" +
" value: " + dValue + "n" +
" isSell: " + nIsSell + "n" +
" status: " + nStatus + "n" +
" orderDescriptor: " + nOrderDescriptor + "n");
}
};
JNADll.testCallback(cb);
}
}
c标题QuikWrap.h
#ifdef QUIKWRAP_EXPORTS
#define QUIKWRAP_API extern "C"__declspec(dllexport)
#else
#define QUIKWRAP_API __declspec(dllimport)
#endif
typedef void (__stdcall *TRANS2QUIK_ORDER_STATUS_CALLBACK) (long nMode, DWORD dwTransID, double dNumber, LPCSTR ClassCode, LPCSTR SecCode, double dPrice, long nBalance, double dValue, long nIsSell, long nStatus, long nOrderDescriptor);
QUIKWRAP_API void __stdcall testCallback(TRANS2QUIK_ORDER_STATUS_CALLBACK cb);
c来源QuikWrap.pp
#include "stdafx.h"
#include "QuikWrap.h"
#include "stdio.h"
QUIKWRAP_API void __stdcall testCallback(TRANS2QUIK_ORDER_STATUS_CALLBACK cb){
cb(1, 2, 3, "Hi", "Bye", 4.0, 5, 6, 7, 8, 9);
cb(0, 2, 3, "Hi", "Bye", 4.0, 5, 6, 7, 8, 9);
return;
}
我得到的回调的唯一输出是
testCallback
nMode: 1
dwTransID: 2
number: 3.0
ClassCode: Hi
SecCode: Bye
price: 4.0
balance: 5
value: 6.0
isSell: 7
status: 8
orderDescriptor: 9
然后退出时回调失败
此问题是由于libffi
中的一个错误引起的,其中根据参数大小调整堆栈对齐,这对于stdcall
来说是不正确的行为。
相关文章:
- 逻辑'double free or corruption (fasttop)'错误
- emplace_back和push_back给出错误'double free or corruption (fasttop)'尽管定义了复制和移动构造函数
- C++ 调用析构函数后动态模板队列"double free or corruption (out)"
- ESP-CoAP 服务器调用资源处理程序,不接收包
- 使用函数指针时,ESP 未在函数调用中正确保存
- 调用 dll 函数时"Run-Time Check Failure #0 - The value of ESP"
- std::vector using back(), pop_back(), push_back(), 得到'double free or corruption'错误
- OpenCV VideoCapture Partial Frame Corruption
- 二叉树中shared_ptr "double free or corruption"
- 如何找到导致"malloc(): memory corruption: 0x00"的线
- 为什么这段代码会导致"heap corruption detected"?
- Windows heap corruption C++C
- D3D11 CORRUPTION: ID3D11DeviceContext::RSGetScissorRects
- 我在C++中使用删除运算符时遇到问题。我在运行时不断收到"double free or corruption (fasttop)"错误
- JNA: __stdcall ESP corruption
- Double free() or corruption:C++
- LEA指令"=> 0xb48daed9 <+3479>: lea -0xc(%ebp),%esp"的意义是什么?
- Heap corruption after new char[strlen
- 什么是"one-stop memory corruption"?
- “ESP 的值未在函数调用中正确保存