2019年5月26日 星期日

[log book] 解決VS2008 exe使用VS2015的dll並delete VS2015 dll new出來的變數導致程式崩潰

[問題描述]
延續《 [log book] 解決演算法結果接口介面化的問題 ─ 要改變指標,請用指標的指標(雙重指標)》之後,又遇到了一個問題,由於我的dll是使用VS2015寫的,但機台的子機程式是用VS2008寫的,當我在exe中釋放的時候,就會出問題。
下圖中,要釋放的記憶體空間result是我在exe中宣告出的記憶體空間,作用是接dll中演算法的運算結果的


[解題思路]
讀到zj510大大的博客《跨DLL的内存分配释放问题 Heap corruption》,雖然裡面在探討的議題與我遇到的稍微不一樣,但看到z大所寫到的:「在一个DLL里面分配内存,然后在DLL的调用者EXE那里释放内存。当DLL和EXE里面有一个是使用MT连接CRT的时候就有问题。如果DLL和EXE都使用MD,那么就没有问题。」,我突然想到:「我應該在dll中釋放dll宣告的記憶體」。

[解決方法]
在dll檔的類別及介面(interface)中,多宣告一個方法釋放dll的記憶體空間的方法 ─ releaseResult
介面的宣告如下
#pragma once
#include "HsStruct.h"
typedef void Result;
class HInspectAlgoInterface
{
public:
        virtual ~HInspectAlgoInterface() { ; }
        virtual bool inspect(ImageParam imgParam, wdb_type *wd, hole_type *md) = 0;
        //virtual bool getResult(std::string Type, int *Num, Result **Ret) = 0;
        virtual bool getResult(char* Type, int *Num, Result **Ret) = 0;
        virtual bool releaseResult(Result **Ret) = 0;
};


releaseResult的定義如下
bool IrrBurCheckAlgo::releaseResult(Result **Ret)
{
        try {
               if (*Ret){
                       delete[] * Ret;
                       *Ret = NULL;
               }
               return true;
        }
        catch (std::exception ex) {
               return false;
        }
}



執行結果如下:

結論:dll new出來的記憶體位置最好由dll自己釋放

不過後來我有發現:若使用的VS 版本一樣,且都是用MD,就不會發生這個問題

下面提供測試版的程式碼:

VS 2015 dll的程式碼:(用MD編譯)
HInspectAlgoInterface.h
#pragma once
#include "HsStruct.h"
typedef void Result;
class HInspectAlgoInterface
{
public:
        virtual ~HInspectAlgoInterface() { ; }
        virtual bool inspect(ImageParam imgParam, wdb_type *wd, hole_type *md) = 0;
        virtual bool getResult(char* Type, int *Num, Result **Ret) = 0;
        virtual bool releaseResult(Result **Ret) = 0;
};

HsStruct.h
#ifndef _HSSTRUCT_H_
#define _HSSTRUCT_H_

typedef struct {
        long id;
        long chip;
        long no;
        long Left;
        long Top;
        long width;
        long height;
}wdb_type;

typedef struct{
        long hole_size;
        long hole_x;
        long hole_y;
        long hole_dx;
        long hole_dy;
}hole_type;

typedef struct{
        unsigned char *Src;
        int Width;
        int Height;
} ImageParam;

沒有留言:

張貼留言