Hello,
I am passing some data from dll to labview. It is an array of clusters. Cluster looks like this:
typedef struct
{
LStrHandle longname;
LStrHandle name;
uint8_t intraonly;
uint8_t lossless;
uint8_t lossy;
} CodecInfo, **CodecInfoHdl;
typedef struct CodecInfoArr
{
int32_t dimsize;
CodecInfo Arr[1];
} CodecInfoArr, **CodecInfoArrHdl;
But I think it is reproducable with any kind of array of clusters where are other handles, like LStrHandle in my case.
The operation is pretty straightforward.
I check the incoming handle, I handle the situation where it is empty or filled with data and in the next step I have an empty handle to work with.
So far I have an array handle returned from DSNewHandle allocated for the resulting array size.
I start copying the data, but since there are strings involved, I call my general char2LStrHandle function to fill string handles.
void PrintChar2LVStrHandle(const char *charstr, LStrHandle *StrHandleP, bool forcenew = false)
{
MgErr error = mgNoErr;
std::string temp = "";
if (charstr)
{
temp.assign(charstr);
}
if ((!IsHandleEmpty(StrHandleP)) && !forcenew)
{
error = DSDisposeHandle(*StrHandleP);
if (error != mgNoErr)
throw(WrpExcUser("PrintChar2LVStrHandle()", error));
}
*StrHandleP = (LStrHandle)(DSNewHandle(Offset(LStr, str) + sizeof(uChar)));
if (*StrHandleP == nullptr)
throw(WrpExcUser("Could not allocate string handle", CUSTOMERROR));
//(**StrHandleP)->cnt = 0;
error = LStrPrintf(*StrHandleP, (CStr)"%s", temp.c_str());
if (error != mgNoErr)
throw(WrpExcUser("Could not print to string handle", error));
}
There is a lot of junk&unnecesary code, but the core of the function is to check the handle, and if it is valid, just print into it. The function that checks the handle looks like this:
bool IsHandleEmpty(const LStrHandle *h)
{
MgErr err, heaperr = mgNoErr;
err = DSCheckHandle(*h);
//heaperr = DSHeapCheck(0);
if (err)
return true;
return false;
}
It is just a stupid wrapper around DSCheckHandle.
Now the problem is, that with the way the array handle allocated the array elements, some handle pointers, from time to time point to memory so unfortunately, that the array elements that get processed later have string handle pointer pointing to memory that is already filled with data from previous array filling loop iterations. It is not the exactly same memory, since the data is little off (garbage, count is wrong etc.), but it is sufficient enough for the DSCheckHandle return, that the handle is valid. So the memory gets a treatment like it would be a real handle and it corrupts the labview heap, so when the data gets deallocated, LabView / runtime will crash.
So far I tackled the solution with simple optional parameter (bool forcenew = false) and went through all the function references in code to set the flag if the data comes from new array handles.
Finally the question: Is there more elegant solution to this, somehow correctly check the incoming string handle ?