- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在研究将结果输出为 matlab 的 .mat 文件格式的研究模型,并最初与 matlab 库链接以使用其文件输出功能。最近,需求发生了变化(谁能猜到),以前只有 linux 的代码现在必须在 windows 上编译,最好不需要 matlab 来构建——但仍然输出 .mat 文件。
所以我搜索并找到了 libmatio (http://sourceforge.net/projects/matio/)。虽然这在 linux 中很容易链接(你只需从存储库安装它),但它在 windows 上很糟糕(基本上没有关于在 windows 上构建它的信息)。事实上,Windows 支持似乎在 1.3.3 版本(早在 2008 年)中就被默默地删除了。
此外,API 与 matlab 提供的 API 完全不同,后者需要我重写/重组大量代码。
所以我想出了这个疯狂的主意......我需要一个 Matlab API 的直接替代品,最好不使用库(以便非程序员可以轻松编译),所以我开始编写一个。
我只是在实现我需要的功能(编写 double 组、字符串和复数 double 组,以及结构和结构嵌套)。所有这些都已经可以正常工作,除了一个:结构数组。
所有 matlab 数据都包含在一个名为“mxArray”的结构中,并且根据其类型,它包含指向 double 、复数 double 或一个或多个其他 mxArray 的指针。
将 mxArray 写入文件之前的最后一步是通过调用 calcArraySize()
计算其大小(及其子项的大小)(以字节为单位)。
这在某些时候会导致段错误,因为我正在尝试访问空指针。为了查明原因,我通过 valgrind 运行代码。一如既往,我尽量按出现的顺序处理任何问题,因为它们可能是后来发生的事情的原因。
所以 valgrind 告诉我的第一件事是:
==8405== Invalid write of size 8
==8405== at 0x00404541: mxSetFieldByNumber (mxSetFieldByNumber.c:18) [A]
==8405== by 0x00411679: calcAllRayInfo (calcAllRayInfo.c:156)
==8405== by 0x0041dd42: main (cTraceo.c:111)
==8405== Address 0x5500250 is 0 bytes inside a block of size 4 alloc'd
==8405== at 0x04c28f9f: malloc (vg_replace_malloc.c:236)
==8405== by 0x00401066: mallocChar (toolsMemory.c:69)
==8405== by 0x00404314: mxCreateStructMatrix (mxCreateStructMatrix.c:43) [B]
==8405== by 0x00411235: calcAllRayInfo (calcAllRayInfo.c:105)
==8405== by 0x0041dd42: main (cTraceo.c:111)
注意:我在下面的代码中标记了 [A] 和 [B]。
结构定义(仅显示相关成员):
struct mxArray{
bool isStruct; //determines if this mxArray is a structure (which contains other mxArrays)
bool isChild; //determines wheter this mxArray is a Child of another (when set, its name will not be written to the matfile, as it is already defined in the parent's fieldnames
uintptr_t nFields;
char **fieldNames; //something like: {"theta","r","z"};
struct mxArray **field; //pointer to member mxArrays. only used when isStruct is set.
};
typedef struct mxArray mxArray;
我用来为 structMatrix 及其内容分配内存的函数:
mxArray* mxCreateStructMatrix(uintptr_t nRows, uintptr_t nCols, uintptr_t nFields, const char **fieldNames){
/*
* creates a 2D array of structures
*/
mxArray* outArray = NULL;
/* do some input value validation */
// allocate memory
outArray = malloc(nRows*nCols*sizeof(mxArray));
if (outArray == NULL){
fatal("mxCreateStructMatrix(): memory allocation error.");
}
// allocate memory for structure members (fields)
for (uintptr_t iStruct=0; iStruct<nCols*nRows; iStruct++){
outArray[iStruct].nFields = nFields;
outArray[iStruct].fieldNames = malloc(nFields*sizeof(char*));
//copy fieldnames into struct info
for (uintptr_t iField=0; iField<nFields; iField++){
//NOTE: strlen returns length of string not including the terminating NULL character
outArray[iStruct].fieldNames[iField] = mallocChar(strlen(fieldNames[iField])+1); // [B] <=======
strncpy(outArray[iStruct].fieldNames[iField], fieldNames[iField], strlen(fieldNames[iField]));
}
outArray[iStruct].field = NULL;
outArray[iStruct].field = malloc(nFields*sizeof(mxArray*));
if (outArray[iStruct].field == NULL){
fatal("mxCreateStructMatrix(): memory allocation error.\n");
}
}
return outArray;
}
mxArrays 存在另外两个分配函数:
mxArray* mxCreateDoubleMatrix(uintptr_t nRows, uintptr_t nCols, uintptr_t numericType){
/*
* creates a 2D array of double precision floating point values.
* can be real or complex.
*/
[snip]
}
mxArray* mxCreateString(const char *inString)
/*
* creates an mxArray containing a string.
*/
[snip]
}
此函数将一个 mxArray 指定为另一个 mxArray 的子元素:
void mxSetFieldByNumber(mxArray* mxStruct, //pointer to the mxStruct
uint32_t index, //linear index of the element
uint32_t iField, //index of the structure's field which we want to set.
mxArray* inArray){ //the mxArray we want to assign to the mxStruct
/*
* Assigns an mxArray to one of the fields of a structArray
*/
inArray->isChild = true; //determines that this mxArray is a child of another one
mxStruct[index].field[iField] = inArray; // [A] <===============
}
用法是:
//create parent mxArray:
mxStruct = mxCreateStructMatrix(1, //number of rows
1, //number of columns
2, //number of fields in each element
fieldNames1); //list of field names
//create children:
mxY = mxCreateDoubleMatrix(1 ,1, mxREAL);
mxZ = mxCreateDoubleMatrix(1 ,1, mxREAL);
mxSubStruct = mxCreateStructMatrix(1, //number of rows
1, //number of columns
3, //number of fields in each element
fieldNames2); //list of field names
/* copy some values into the mxArrays */
[snip]
//link children to parents
mxSetFieldByNumber( mxStruct, //pointer to the parent mxArray
0, //index of the element (linear)
0, //position of the field (in this case, field 0 is "w"
mxY); //the mxArray we want to add to the mxStruct
mxSetFieldByNumber( mxStruct, 0, 1, mxZ);
mxSetFieldByNumber( mxSubStruct, 0, 0, mxY);
mxSetFieldByNumber( mxSubStruct, 0, 1, mxZ);
mxSetFieldByNumber( mxStruct, 0, 2, mxSubStruct);
显然,mxStruct[index].field[iField] = inArray;
正在写入 mxStruct[index].fieldNames
,从而留下 mxStruct[index ].field[iField] == NULL
,然后在我尝试访问它时导致段错误。
怎么会这样?在调用 mxCreateStructMatrix
时两者都被正确分配,那么这些指针怎么会重叠呢?我忽略了什么?
最佳答案
我认为问题出在你最后的陈述上:
mxSetFieldByNumber( mxStruct, 0, /* THIRD FIELD */ 3, mxSubStruct);
您正在尝试为 mxStruct
的第三个字段分配另一个嵌套结构变量,问题是 mxStruct
只定义了两个字段:
mxStruct = mxCreateStructMatrix(1, 1, /* TWO */ 2, fieldNames1);
与 MATLAB 不同,您的代码(据我所知)不支持动态添加结构字段:
%# -- MATLAB code --
s = struct('f1',[], 'f2',[]);
s.f3 = 99; %# add a new field
这不会很难实现,您只需重新分配指针数组以容纳更多字段并增加字段计数。
关于c - 编写用于编写 .matfiles 的 Matlab C API 的替代品,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8066404/
由于数据量较大且自动保存频繁,我决定将保存方法从标准 save() 函数更改为使用 matfile 对象进行部分保存: https://www.mathworks.com/help/matlab/re
我需要将一个太大而无法放入内存的数组写入 .mat 二进制文件。这可以通过 matfile 来完成命令,它允许随机访问光盘上的 .mat 文件。 我正在尝试在此文件中预分配数组,以及 MathWork
我正在研究将结果输出为 matlab 的 .mat 文件格式的研究模型,并最初与 matlab 库链接以使用其文件输出功能。最近,需求发生了变化(谁能猜到),以前只有 linux 的代码现在必须在 w
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 4 年前。
我是一名优秀的程序员,十分优秀!