发布-构建DLL的行为出乎意料

Release-Build of DLL behaves unexpected

本文关键字:出乎意料 DLL 构建 发布      更新时间:2023-10-16

我有一个VS2013项目来构建我使用JNA从Java调用的DLL。一切工作预期,只要我使用调试配置-但当使用任何优化(配置属性-> C/c++ ->优化->除"禁用(/Od)"之外的一切),行为变得意想不到的。我想知道为什么会这样,在这种情况下我是否依赖于未定义行为?

我对两次调用createObject()的期望是:第一次调用应该返回true(因为实例未初始化并且将被初始化),第二次调用应该返回false(因为实例应该已经初始化)。然而,如果我使用发布-构建(或激活优化调试-构建)createObject()返回true为每个连续调用。

My c++ Code:

#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型缺省转换为布尔型。您应该确保您的本机代码返回具有定义良好的大小的内容,以便JNA可以可靠地进行转换。

JNA需要为所有内容定义良好的大小,以便正确执行Java到本机的转换。