簡體   English   中英

為什么指針的值會意外改變?

[英]Why does the value of a pointer unexpectedly change?

我已經將 C++ 集成到 Matlab 中; 在我的示例中,有三個簡單的文件:一個 Matlab 腳本main.m 、一個 Matlab 類文件myClass.m和一個 C++ 文件myMex.cpp

main.m我調用類給出一個字符串作為輸入。

main.m :

myVar = myClass('test.bin');

myClass.m :

classdef myClass < handle    
    properties
        bitStreamName;
        cabac_handle;
    end
    methods
        function obj = myClass(fn)      
            obj.bitStreamName = fn;
            obj.cabac_handle = myMex('First', obj.bitStreamName);
            myMex('Second', obj.cabac_handle);
        end
    end
end

myMex.cpp :

#include "mex.h"
#include <iostream>
using namespace std;

void _main();

class CABAC {
public:
    CABAC() {};
    ~CABAC() {};
    char* fn;
};

// the MEX interface function
void mexFunction(
    int nlhs, // Number of expected output mxArrays
    mxArray *plhs[], // Array of pointers to the expected output mxArrays
    int nrhs, // Number of input mxArrays
    const mxArray *prhs[] // Array of pointers to the input mxArrays
    )

{
    CABAC *c; // pointer to (new) instance of the CABAC class
    char* fn = 0;
    char cmd[64]; // temp char array to hold the command

    // start parsing the input command
    mxGetString(prhs[0], cmd, sizeof(cmd));
    string inputCmd(cmd);

    if (inputCmd == "First")
    {
        // get the filename string
        fn = mxArrayToString(prhs[1]);
        c = new CABAC;
        uintptr_t c_value = (uintptr_t)c;
        plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
        *mxGetPr(plhs[0]) = c_value; // return pointer to matlab environment
        c->fn = fn;
        mexPrintf("Pointer: %p\n", c);
        mexPrintf("Filename: %s\n", c->fn);
    }
    else if (inputCmd == "Second")
    {
        uintptr_t my_value = *mxGetPr(prhs[1]);
        CABAC *my_pointer =  (CABAC *)my_value;
        mexPrintf("Pointer: %p\n", my_pointer);
        mexPrintf("Filename: %s\n", my_pointer->fn);
    }
}

第一次myMex.cpp ,我創建了一個CABAC類的對象,並且字符串"test.bin"與它的屬性fn相關聯。 最后,將指針的值返回給Matlab 環境。

第二次,我只是簡單地獲得了指向先前實例化對象的指針,這里發生了一些奇怪的事情。 特別是,同時打印指針地址和屬性fn ,前者總是正確的(即對象的地址相同),但后者有時正確(打印"test.bin" )有時完全和隨機錯誤(奇怪的字符串出現,每次執行都不同)。

要執行我的代碼,您可以在使用以下指令編譯myMex.cpp后簡單地運行main.m

mex CXXFLAGS="\$CXXFLAGS -std=c++11" -g myMex.cpp

或者

mex COMPFLAGS="\$CXXFLAGS -std=c++11" -g myMex.cpp

你能幫我理解文件名會發生什么嗎?

編輯:似乎c在第一次myMex調用后被刪除。 如何將指向CABAC對象(及其所有屬性)的指針保存在內存中?

這里有很多問題。 首先,您正在將指針轉換為double ,它不保留其表示形式:

uintptr_t c_value = (uintptr_t)c;
plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
*mxGetPr(plhs[0]) = c_value; // return pointer to matlab environment

相反,創建一個 64 位整數數組來保存指針:

plhs[0] = mxCreateNumericMatrix(1, 1, mxUINT64_CLASS, mxREAL);
*(uint64_t*)mxGetData(plhs[0]) = (uint64_t)c;

(從 MATLAB R2018a mxGetData ,每種類型都有 mxGetData 的替代品,在這種情況下它將是mxGetUint64s )。

其次,當 MEX 文件被卸載時,內存new ed 可能會被刪除。 這可能隨時發生。 為防止出現這種情況,請使用mexLock將 MEX 文件鎖定在內存中。 為防止內存泄漏,您將需要包含在完成后刪除內存的代碼。 由於您的 MATLAB 類是句柄類,因此可以完成此操作。

第三,很容易用錯誤的指針調用 MEX 文件,這可能會導致整個 MATLAB 崩潰。 您當前的實現無法解決這個問題。

第四,正如Navan所指出的,以下行創建了字符串的副本,但位於由 MATLAB 維護的內存緩沖區中:

fn = mxArrayToString(prhs[1]);

MATLAB會自動刪除根據所分配的所有內存mxMalloc ,並在年底相似mexFunction 因此, fn將指向已釋放的內存。 您需要在您管理的內存中手動創建一個副本。 我建議您將字符串復制到std::string

class CABAC {
  public:
  std::string fn;
};

fn = mxArrayToString(prhs[1]); // Will copy the string to `fn`.

但是,相反,我會推薦一種不同的方法:

  • 在您的 MEX 文件中,保留指向已分配對象的指針數組。
  • MEX 文件不返回指針,而是返回數組索引。
  • MEX 文件現在可以測試輸入“句柄”是否在數組的有效范圍內,以及該數組是否包含有效指針或NULL指針(例如,對於已刪除的對象或尚未使用的數組元素)然而)。
  • 鎖定 MEX 文件,但允許使用命令將其解鎖。 解鎖 MEX 文件也會刪除所有分配的對象。
  • 您可以包含在最后一個分配的對象被刪除時自動解鎖 MEX 文件的邏輯。

您應該知道全局變量將在調用 MEX 文件之間保持不變(只要它被鎖定)。 因此,您需要一個全局數組(在mexFunction之外定義)來存儲指針。或者,在mexFunction內聲明數組是static的。

這個 MEX 文件實現了這里描述的建議,雖然它不是一個簡單的例子,但我希望它作為一個起點可能有用。 在這個函數中,我使用std::map而不是普通數組來存儲句柄。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM