PWork initialization in c++ s-Function with 'Update Diagram' routine

9 ビュー (過去 30 日間)
Mathias Hakenberg
Mathias Hakenberg 2019 年 3 月 5 日
回答済み: ye chen 2020 年 5 月 22 日
I am using a c++ s-Function with persistent objects, that are stored in the PWork vector, following the documentation example. The callback methods look like this:
1.Initialize Sizes:
static void mdlInitializeSizes(SimStruct *S)
{
ssSetNumPWork(S, 1);
}
2. Start Model:
static void mdlStart(SimStruct *S)
{
ssGetPWork(S)[0] = new uint8_T(0); // some persistent variable
}
3. Do something with the variable:
static void mdlOutputs(SimStruct *S, int_T tid)
{
uint8_T* aliveCounter = static_cast<uint8_T*>(ssGetPWorkValue(S,0));
(*aliveCounter)++;
}
4. Free the memory after model finishes:
static void mdlTerminate(SimStruct *S)
{
uint8_T* aliveCounter = static_cast<uint8_T*>(ssGetPWorkValue(S, 0));
delete aliveCounter;
}
Everything works fine, if the model is simulated. However, if the Simulink model just gets updated (e.g. via Simulation -> Update Diagram), Matlab crashes with a Memory error. The reason for this is, that 'Update Diagram' only invokes the mdlInitializeSizes and mdlTerminate callbacks. Thus, the PWork vector-size is set to 1, but the value is not initialized, because mdlStart is not called. (Initialization of PWork in mdlInitializeSizes is not possible).
Finally, when the mdlTerminate function is called ssGetPWorkValue(S, 0) trys to access an undefined memory block and Matlab crashes.
Do you have any recommendations, how to avoid this? Is there any way of distinguishing, whether the function is called at the end of a simulation, or just as part of a 'Update Diagram' routine?

回答 (2 件)

Mark McBroom
Mark McBroom 2019 年 3 月 6 日
Check aliveCounter for NULL before trying to delete it.
  2 件のコメント
Mathias Hakenberg
Mathias Hakenberg 2019 年 3 月 7 日
The program crashes when executing ssGetPWorkValue(S, 0). That is before checking the aliveCounter for NULL.
In more detail:
ssGetPWorkValue(S, 0) expands to S->work.pWork[0] , but pWork is not initialized.
Mark McBroom
Mark McBroom 2019 年 3 月 7 日
編集済み: Mark McBroom 2019 年 3 月 7 日
Try code like this:
#define IS_SIMULATION_TARGET(S) (ssRTWGenIsAccelerator(S) || ssIsRapidAcceleratorActive(S) || ssRTWGenIsModelReferenceSimTarget(S) || (ssGetSimMode(S)==SS_SIMMODE_NORMAL) || (ssGetSimMode(S)==SS_SIMMODE_SIZES_CALL_ONLY) || !((ssRTWGenIsCodeGen(S) || ssGetSimMode(S)==SS_SIMMODE_EXTERNAL) && GetRTWEnvironmentMode(S)==0))
static void mdlOutputs(SimStruct *S, int_T tid)
{
if (IS_SIMULATION_TARGET(S)) {
uint8_T* aliveCounter = static_cast<uint8_T*>(ssGetPWorkValue(S, 0));
}

サインインしてコメントする。


ye chen
ye chen 2020 年 5 月 22 日
Does your problem get solved?

製品


リリース

R2017b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by