日常技术积累

  1. C++ DLL的类接口形参传递异常

  • 情况一:形参中含有CString,参数栈内存异常

原因分析:形参中,字符串的传递,不要使用临时变量拷贝赋值,这样导致了形参的栈数据异常,导致形参中的ini类型的变量也出现了异常

解决方案:字符串的传递使用引用或者char*代替

class __declspec(dllimport) CInstrumentCtrlSample
{
public:
    //该写法正常
    bool Connect(const CString& resourceName, int tryTimes, CString& errMsg); 
        
    //该写法异常:如果写成下面这样会出现int参数异常,errMsg的内存也无法正常读取,具体原因未知。
    bool Connect(CString resourceName, int tryTimes, CString& errMsg);  
}
  • 情况二:形参中含有STL类型数据,如std::map,std::list等

原因分析:DLL接口不能使用STL,具体参考:跨dll访问STL的map的问题 _followme163的博客-CSDN博客

解决方案:STL改为类的私有变量,暴露容器的操作函数,例如:

class DLL_API NeowayPrint
{
public:
    void ClearBtwSubStringMap() {
        m_BtwSubStringMap.clear();
    }
    void SetBtwSubString(const std::string& key, const std::string& value) {
        m_BtwSubStringMap[key] = value;
    }

private:
    std::map <std::string, std::string> m_BtwSubStringMap;
};

原因分析:string的内存是随内容变化的,这导致了结构体中的数据内存分布变更,导致在DLL接口的参数传递中找不到正确的数据指针,例如下面的代码,std::string变量放在了最前面,从而导致了这个结构体形参传入时,后面的int、bool等数据因为找不数据地址导致数据异常

typedef struct _PrintExecutionParameter_
{
    std::string PrinterName; //打印机名称
    int printCountMax; //连续打印最大数量(达到此数量后会提示)
    int PrintNum; //打印数量(执行一次打印动作,打印多少张)
    int SamebtPrintNum; //一张纸打印多少张模板
    bool IsShowPrintDialog; //是否显示打印窗口
}PrintExecutionParameter, *pPrintExecutionParameter;

解决方案:将std::string变量放到最后

typedef struct _PrintExecutionParameter_
{
    int printCountMax; //连续打印最大数量(达到此数量后会提示)
    int PrintNum; //打印数量(执行一次打印动作,打印多少张)
    int SamebtPrintNum; //一张纸打印多少张模板
    bool IsShowPrintDialog; //是否显示打印窗口
    std::string PrinterName; //打印机名称
}PrintExecutionParameter, *pPrintExecutionParameter;
  • 情况四:从接口中返回string,无论是通过返回值返回,还是通过形参引用参数返回,都导致了数据崩溃

原因分析:string的内存在DLL接口函数中申请的,而在返回时,申请的内存被释放了,从而导致接口调用者在获取数据时出现了堆栈内存异常崩溃

#ifdef DLL_PRINT
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif

DLL_API std::string GetBtwFilePath() const;
DLL_API void GetBtwFilePath(std::string& strBtwFilePath) const;

解决方案:尽量都使用char*等指针来替代string,增强DLL接口的兼容性(情况一也建议此方案)

#ifdef DLL_PRINT
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif

DLL_API void GetBtwFilePath(char* const _Destination, rsize_t const _DestinationSize) const;

情况五:接口调用时编译正常,Demo测试也正常,但是合入到实际工程中调用时奔溃,或是实际工程的其他函数在合入接口前正常,在合入后出现了异常

原因分析:接口中涉及的一些依赖DLL版本与实际工程中涉及的DLL版本冲突,例如:接口中用到了A.dll其版本3.1,实际工程中也用到了A.dll其版本是2.2

解决方案:令两者都使用相同版本的A.dll

  1. 待续...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值