504 views
in Embedded Wizard Studio by

I have faced a strange bug in EW 9.00. I'm using the STM32 Platform Package with a STM32F746.

When assigning a constant string to a variable, the variable doesn't hold the desired value.

I could narrow it down to this function:

  $rect <1880,80,2080,120>
  method string languageObj2Str( arg language lang )
  {
    trace "languageObj2Str parameter = ", lang;

    var string langC = "";

    if(lang == English){
      trace "Equals English";
      langC = "EN";
    }else if(lang == Russisch){
      trace "Equals Russisch";
      langC = "RU";
    }else if(lang == Franzoesisch){
      trace "Equals Franzoesisch";
      langC = "FR";
    }else if(lang == Polnisch){
      trace "Equals Polnisch";
      langC = "PL";
    }else if(lang == Spanisch){
      trace "Equals Spanisch";
      langC = "ES";
    }else if(lang == Niederlaendisch){
      trace "Equals Niederlaendisch";
      langC = "NL";
    }else{
      trace "Equals default";
      trace "languageObj2Str before assignment = ", langC;
      langC = "DE";
      // default value
      trace "languageObj2Str after assignment = ", langC;
    }

    trace "languageObj2Str result = ", langC;
    return langC;
  }

The debug-output on the Hardware is as follows, when supplying the argument with language "Default":

trace: "languageObj2Str parameter = ", language:0x00000000
trace: "Equals default"
trace: "languageObj2Str before assignment = ", ""
trace: "languageObj2Str after assignment = ", "EN"
trace: "languageObj2Str result = ", "EN"

So the language was correctly set to Default, since it is getting in the last else-branch "Equals default". Before the Assignment, langC is empty, as expected, since we initialised it as an empty string.

But then the returned String after assignment is "EN". But we assigned "DE". How could that be?

1 Answer

0 votes
by
 
Best answer

Hello,

the behaviour you have observed is definitely not correct. In the first step I would analyse the generated C code. Can you provide us the C file containing the method languageObj2Str()? If you are not sure which file is the right one, send us the complete generated code. You can send it directly via e-mail to support@embedded-wizard.de.

Best regards

Paul Banach

by

Hi Paul,

in the meantime i have investigated this further by looking in the generated code as you suggest:

the root-cause, i think is burried in the  EwLoadString method. I think, that this method simply returns the location of the constant given as its argument. So the string variable points to the ram-address where the constant is located. Some dumb string-modification on our side writes to this variable, thus changing the constant string.

here is the chora-code that makes the problem:

$rect <1990,410,2240,450>
  method string ReadLanguageRaw()
  {
    var string langC = "DE";
    $if !$prototyper
    native (langC){
      langC[0] = eeprom.language[0];
      langC[1] = eeprom.language[1];
      langC[2] = 0;
      langC[3] = 0;
    }
    $endif
    return langC;
  }

this is generated to ansiC:

/* 'C' function for method : 'Supervisor::DeviceClassLT.ReadLanguageRaw()' */
XString SupervisorDeviceClassLT_ReadLanguageRaw( SupervisorDeviceClassLT _this )
{
  XString langC;

  /* Dummy expressions to avoid the 'C' warning 'unused argument'. */
  EW_UNUSED_ARG( _this );

  langC = EwLoadString( &_Const0006 );
  {
    langC[0] = eeprom.language[0];
    langC[1] = eeprom.language[1];
    langC[2] = 0;
    langC[3] = 0;
  }
  return langC;
}

and here is the code-snipet, that is generated from the above languageObj2Str:

XString SupervisorDeviceClassLT_languageObj2Str( SupervisorDeviceClassLT _this, 
  XLangId lang )
{
  XString langC;

  /* Dummy expressions to avoid the 'C' warning 'unused argument'. */
  EW_UNUSED_ARG( _this );

  EwTrace( "%s%l", EwLoadString( &_Const000F ), lang );
  langC = 0;

  if ( lang == English )
  {
    EwTrace( "%s", EwLoadString( &_Const0010 ));
    langC = EwLoadString( &_Const0009 );
  }
  else
    if ( lang == Russisch )
    {
      EwTrace( "%s", EwLoadString( &_Const0011 ));
      langC = EwLoadString( &_Const000A );
    }
    else
      if ( lang == Franzoesisch )
      {
        EwTrace( "%s", EwLoadString( &_Const0012 ));
        langC = EwLoadString( &_Const000B );
      }
      else
        if ( lang == Polnisch )
        {
          EwTrace( "%s", EwLoadString( &_Const0013 ));
          langC = EwLoadString( &_Const000C );
        }
        else
          if ( lang == Spanisch )
          {
            EwTrace( "%s", EwLoadString( &_Const0014 ));
            langC = EwLoadString( &_Const000D );
          }
          else
            if ( lang == Niederlaendisch )
            {
              EwTrace( "%s", EwLoadString( &_Const0015 ));
              langC = EwLoadString( &_Const000E );
            }
            else
            {
              EwTrace( "%s", EwLoadString( &_Const0016 ));
              EwTrace( "%s%s", EwLoadString( &_Const0017 ), langC );
              langC = EwLoadString( &_Const0006 );
              EwTrace( "%s%s", EwLoadString( &_Const0018 ), langC );
            }

  EwTrace( "%s%s", EwLoadString( &_Const0019 ), langC );
  return langC;
}

So the _Const0006 gets modified by ReadLanguageRaw.

This is extremely hard to see in the Chora-Sourcecode. I would expect, when i assign a Constant to a Variable, that this will be copied to a new location where the variable points to...

This now has been popped up, because i have moved all the functions that interact with the middleware to one class. before they were distributed through different units and thus the constant get declared separatly in each unit, so the constant got overwritten in one unit, but it was read from another unit...

greetings Daniel Schroll

by

Hello Daniel,

I'm slightly relieved. In this case the observed behaviour is comprehensible. Embedded Wizard treats strings in a special manner managing the respective memory areas, sharing equal strings to save memory and automatically releasing memory of not used strings. As long as you implement code in Chora these mechanisms work as expected. If you try some problematic operation (e.g. modification of a constant), the Chora compiler will report an error.

In your ReadLanguageRaw() method you have implemented some trick with native code where you directly access and overwrite the contents of an existing string. Since the respective memory area contains the constant string "DE", the native code overwrites this contents.

In this context I would refer to our documentation Be careful when exchanging strings. It provides some hints how to access/create strings in native code. Consequently, I would implement the method ReadLanguageRaw() as follows. Please note the usage of the function EwNewStringChar():

method string ReadLanguageRaw()
{
  var string langC = "";

  $if !$prototyper
    native ( langC ){
      /* First create a new string able to store 4 characters. You will
         get a private instance of the string */
      langC = EwNewStringChar( 0, 4 );

      /* Now you can modify this string instance */
      langC[0] = eeprom.language[0];
      langC[1] = eeprom.language[1];
    }
  $endif

  return langC;
  }

Best regards

Paul Banach

by
Thank you very much! That works.

greetings Daniel Schroll

Ask Embedded Wizard

Welcome to the question and answer site for Embedded Wizard users and UI developers.

Ask your question and receive answers from the Embedded Wizard support team or from other members of the community!

Embedded Wizard Website | Privacy Policy | Imprint

...