Memory management 在没有内存异常的情况下,如何使用DSSetHandleSize()为集群的LabVIEW数组分配内存
我能够可靠地使用LabVIEW字符串数组。当我尝试对集群数组执行相同的操作时,当增加句柄大小时,它总是在从DLL返回时崩溃 代码是:Memory management 在没有内存异常的情况下,如何使用DSSetHandleSize()为集群的LabVIEW数组分配内存,memory-management,dll,labview,Memory Management,Dll,Labview,我能够可靠地使用LabVIEW字符串数组。当我尝试对集群数组执行相同的操作时,当增加句柄大小时,它总是在从DLL返回时崩溃 代码是: typedef struct { uint8_t depth; LStrHandle name; LStrHandle child; } TreeElem; typedef struct { int32_t dimSize; TreeElem Element[1]; } **TreeHdl; MSEXPOR
typedef struct {
uint8_t depth;
LStrHandle name;
LStrHandle child;
} TreeElem;
typedef struct {
int32_t dimSize;
TreeElem Element[1];
} **TreeHdl;
MSEXPORT void BuildTreeCtl(int32_t depth, uint32_t xmlNodePtr, TreeHdl TreeCluster)
{
xmlNode *cur_node, *chile_node;
for (cur_node = (xmlNode *) xmlNodePtr; cur_node; cur_node = cur_node->next) {
if (cur_node->type == XML_ELEMENT_NODE) {
DSSetHandleSize(TreeCluster, sizeof(int32) + (sizeof(TreeElem) * ((*TreeCluster)->dimSize + 1)));
int idx = (*TreeCluster)->dimSize++;
if (cur_node->name != NULL) {
LV_STR_NEW(((*TreeCluster)->Element)[idx].name, (char*) cur_node->name);}
// check for CDATA
for (chile_node = cur_node->children; chile_node; chile_node = chile_node->next) {
if (chile_node->type == XML_CDATA_SECTION_NODE) {
if (chile_node->content != NULL) {
LV_STR_NEW(((*TreeCluster)->Element)[idx].child, (char*) chile_node->content);
}
}
}
BuildTreeCtl(depth + 1, (uint32_t) cur_node->children, TreeCluster);
}
}
}
事实证明,当增加数组大小时,
DSSetHandleSize()
(至少适用于LabVIEW 2013及更早版本)不会将新内存初始化为零。此外,它可能会使用与进入时不同的句柄分配新的内存块-它确实会将现有数据可靠地传输到新的内存分配,但新内存块中存在的任何内容都会导致LabVIEW在返回时崩溃,这肯定是因为LabVIEW使用了垃圾指针
代码应为:
MSEXPORT void BuildTreeCtl(int32_t depth, uint32_t xmlNodePtr, TreeHdl TreeCluster)
{
xmlNode *cur_node, *chile_node;
for (cur_node = (xmlNode *) xmlNodePtr; cur_node; cur_node = cur_node->next) {
if (cur_node->type == XML_ELEMENT_NODE) {
DSSetHandleSize(TreeCluster, sizeof(int32) + (sizeof(TreeElem) * ((*TreeCluster)->dimSize + 1)));
int idx = (*TreeCluster)->dimSize++;
调用DSSetHSzClr而不是DSSetHandleSize。调用DSSetHSzClr而不是DSSetHandleSize.Ouch。您可能认为会提到清除数据或引用
DSSetHSzClr()
,但它们只引用NumericArrayResize()
。我会把它放在NI和糟糕的文档上。谢谢
#if 0 // brute force
(((*TreeCluster)->Element)[idx]).depth = depth;
(((*TreeCluster)->Element)[idx]).name = NULL;
(((*TreeCluster)->Element)[idx]).child = NULL;
#elif 0 // generic
uint8_t *Ptr = (uint8_t *) &(((*TreeCluster)->Element)[idx]);
for (int j=0; j<sizeof(TreeElem); j++) {*(Ptr + j) = 0;}
#else
uint8_t *Ptr = (uint8_t *) &(((*TreeCluster)->Element)[idx]);
memset(Ptr, 0, sizeof(TreeElem));
#endif
if (cur_node->name != NULL) {
LV_STR_NEW(((*TreeCluster)->Element)[idx].name, (char*) cur_node->name);}
// check for CDATA
for (chile_node = cur_node->children; chile_node; chile_node = chile_node->next) {
if (chile_node->type == XML_CDATA_SECTION_NODE) {
if (chile_node->content != NULL) {
LV_STR_NEW(((*TreeCluster)->Element)[idx].child, (char*) chile_node->content);
}
}
}
BuildTreeCtl(depth + 1, (uint32_t) cur_node->children, TreeCluster);
}
}
}