为什么指针的值会意外更改
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: %pn", c);
mexPrintf("Filename: %sn", c->fn);
}
else if (inputCmd == "Second")
{
uintptr_t my_value = *mxGetPr(prhs[1]);
CABAC *my_pointer = (CABAC *)my_value;
mexPrintf("Pointer: %pn", my_pointer);
mexPrintf("Filename: %sn", 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
你能帮我了解一下文件名是怎么回事吗?
EDIT:似乎在第一次调用myMex
之后删除了c
。如何将指向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
的替代方案,在这种情况下,它将是mxGetUint64s
)。
其次,当MEX文件被卸载时,存储器new
ed可能会被删除。这种情况随时可能发生。为了防止这种情况发生,请使用mexLock
将MEX文件锁定在内存中。为了防止内存泄漏,你需要包含在处理完内存后删除内存的代码。由于你的MATLAB类是一个句柄类,所以这是可以实现的。
第三,用错误的指针调用MEX文件非常容易,这可能会导致所有MATLAB崩溃。对于您当前的实现来说,这是无法解决的。
第四,正如Navan所指出的,下面一行创建了字符串的副本,但在MATLAB维护的内存缓冲区中:
fn = mxArrayToString(prhs[1]);
MATLAB将在mexFunction
结束时自动删除mxMalloc
和类似程序分配的所有内存。因此,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
而不是普通数组来存储句柄。
- 使用取消引用的指针的多态性会产生意外的结果.为什么?
- 如果我删除指针,我的C++程序会意外删除系统文件吗?
- 指针数组中的意外结果
- 使用指针访问数组元素时出现意外结果
- 字符指针不断意外更改
- 从指针返回对象时出现意外的析构函数调用
- 试图读取AIFF文件意外错误与指针位置等有关
- 将 std::sort 与指向整数变量的指针一起使用会产生意外的输出
- Cout删除了(未签名的字符)指针,给了我意外的结果
- 为什么EXPECT_CALL测试在使用取消引用的指针时意外通过
- 为什么指针的值会意外更改
- 超出范围的指针的意外输出
- 将指针传递到私有变量时出现意外行为
- 在继承中使用delete的意外行为,基指针对象指向派生程度最高的类
- 删除矢量中的指针后出现意外行为
- C++分配的指针显示意外行为
- 将一个char指针赋值给另一个(不同的地址)的意外结果
- 使用指针表示法反转cstring时出现意外结果
- 在宿主结构体上设置指针时出现意外结果
- 比较C++中两个与指针相关的整数值的意外结果