DLL 的 Release-Build 行为异常
Release-Build of DLL behaves unexpected
我有一个 VS2013 项目来构建我使用 JNA 从 Java 调用的 DLL。一切正常,只要我使用调试配置 - 但是当使用任何优化时(配置属性 -> C/C++ -> 优化 -> "Disabled (/Od)" 之外的所有其他内容),行为变得意想不到.我想了解为什么会这样 - 在这种情况下我依赖未定义的行为吗?
我对调用 createObject()
两次的期望是:第一次调用应该 return true
(因为实例未初始化并将被初始化),第二次调用应该 return false
(因为实例应该已经初始化)。但是,如果我使用 Release-Build(或在 Debug-Build 中激活优化)createObject()
是 returning true
每次连续调用。
我的 C++ 代码:
#include <windows.h>
#include <memory>
#define DLL_EXPORT
#ifdef DLL_EXPORT
# define CALLCONV extern "C" __declspec(dllexport)
#else
# define CALLCONV extern "C" __declspec(dllimport)
#endif
class MyType{
};
std::unique_ptr<MyType> instance = nullptr;
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved){
switch (fdwReason){
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
default:
break;
}
return TRUE;
}
CALLCONV bool createObject(){
bool retVal = true;
if (instance == nullptr){
instance = std::unique_ptr<MyType>(new MyType());
}else{
retVal = false;
}
return retVal;
}
仅供参考,我的调用 JNA 代码(但我想,如果我也从本机代码调用它,也会出现同样的问题):
import com.sun.jna.Library;
import com.sun.jna.Native;
public class main {
public interface TestLibrary extends Library {
TestLibrary INSTANCE = (TestLibrary)Native.loadLibrary("Test", TestLibrary.class);
boolean createObject();
}
public static void main(String[] args) {
try {
System.out.println(TestLibrary.INSTANCE.createObject());
System.out.println(TestLibrary.INSTANCE.createObject());
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load.\n" + e);
System.exit(1);
}
}
}
bool 的大小取决于实现。 JNA 假定从本机 int 到 boolean 的默认转换。您应该确保您的本机代码返回具有明确定义的大小的内容,以便 JNA 可以可靠地进行转换。
JNA 需要为所有内容定义明确的大小才能正确执行 Java 到本地翻译。
我有一个 VS2013 项目来构建我使用 JNA 从 Java 调用的 DLL。一切正常,只要我使用调试配置 - 但是当使用任何优化时(配置属性 -> C/C++ -> 优化 -> "Disabled (/Od)" 之外的所有其他内容),行为变得意想不到.我想了解为什么会这样 - 在这种情况下我依赖未定义的行为吗?
我对调用 createObject()
两次的期望是:第一次调用应该 return true
(因为实例未初始化并将被初始化),第二次调用应该 return false
(因为实例应该已经初始化)。但是,如果我使用 Release-Build(或在 Debug-Build 中激活优化)createObject()
是 returning true
每次连续调用。
我的 C++ 代码:
#include <windows.h>
#include <memory>
#define DLL_EXPORT
#ifdef DLL_EXPORT
# define CALLCONV extern "C" __declspec(dllexport)
#else
# define CALLCONV extern "C" __declspec(dllimport)
#endif
class MyType{
};
std::unique_ptr<MyType> instance = nullptr;
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved){
switch (fdwReason){
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
default:
break;
}
return TRUE;
}
CALLCONV bool createObject(){
bool retVal = true;
if (instance == nullptr){
instance = std::unique_ptr<MyType>(new MyType());
}else{
retVal = false;
}
return retVal;
}
仅供参考,我的调用 JNA 代码(但我想,如果我也从本机代码调用它,也会出现同样的问题):
import com.sun.jna.Library;
import com.sun.jna.Native;
public class main {
public interface TestLibrary extends Library {
TestLibrary INSTANCE = (TestLibrary)Native.loadLibrary("Test", TestLibrary.class);
boolean createObject();
}
public static void main(String[] args) {
try {
System.out.println(TestLibrary.INSTANCE.createObject());
System.out.println(TestLibrary.INSTANCE.createObject());
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load.\n" + e);
System.exit(1);
}
}
}
bool 的大小取决于实现。 JNA 假定从本机 int 到 boolean 的默认转换。您应该确保您的本机代码返回具有明确定义的大小的内容,以便 JNA 可以可靠地进行转换。
JNA 需要为所有内容定义明确的大小才能正确执行 Java 到本地翻译。