C++ DLL 導出函數:
BOOL WINAPI InsUpdDel(LPSTR lpSqlStr, LPRTNINFO RtnInfo);
結構體:
typedef struct { long ErrCode; char ErrMsg[71]; } RTN_INFO;
VB.NET 調用時,lpSqlStr 傳漢字正常,但 RtnInfo.ErrMsg 返回漢字拋出 0x8007007A (數據區域太小)。
LPSTR (輸入參數) 由調用方分配內存,長度由調用方控制,VB.NET 字符串按 ANSI 編碼封送傳遞,足夠大無問題。LPRTNINFO (輸出參數) 結構體內存由調用方 (VB.NET) 預分配,封送拷貝器按結構體定義大小分配緩衝區。Structure 默認 CharSet.Ansi 時,char[71] 按 1 字節/字符預留 71 字節。但 C++ 可能以 UTF-8 或雙字節字符集寫入,實際字節數超過 71 導致截斷/越界,封送器檢測到目標緩衝區不足拋出異常。將結構體改為兩個獨立輸出參數:
// C++ 修改
DLLEXPORT BOOL WINAPI InsUpdDel(LPSTR lpSqlStr, long* pErrCode, LPSTR pErrMsg, int errMsgBufSize);
// 實現時檢查 errMsgBufSize,安全複製
VB.NET 端聲明:
Declare Function InsUpdDel Lib "xxx" (ByVal sql As String, ByRef errCode As Long, ByVal errMsg As StringBuilder, ByVal bufSize As Integer) As Boolean
Public Structure RTN_INFO
Public ErrCode As Integer
' 擴大到 256 字節
Public ErrMsg As String
End Structure
同時確保 C++ 寫入時不超過緩衝區長度(使用 strncpy_s 或 snprintf)。
跨語言調用盡量避免結構體內嵌固定長度字符數組作為輸出,改用獨立字符串指針+長度參數,更安全可控。