CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Problem with Variable length constant strings

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
loupan



Joined: 22 Oct 2007
Posts: 21

View user's profile Send private message

Problem with Variable length constant strings
PostPosted: Thu Jan 21, 2010 9:40 pm     Reply with quote

Version 4 of the compiler has an efficient way to store variable length strings. From their web page:


Code:
const char strings[][*] =
{
   "HELLO",
   "WORLD",
   "EXTRALONGERWORD"
};



The following is a routine that makes use of the above construct. I use a 'strcpy' to process one of the variable length strings. You will see in the following example that their are 2 identical consecutive strcpy calls. Without the second apparently redundant strcpy, the routine yields a garbage string. With the second strcpy, it works as expected.


Code:
////////////////////////////////////////////////////////////////////////////
// bg_msg_loader - loads a constant msg into user buffer for bar graph messages

void bg_msg_loader (char *usr_buf, int msg_indx)  { 

   const char  strings[][*] =   {

   "BGINT ",    // indx 0
   "BGEXT ",    // 1
   "BGBTH ",    // 2
   "BGOFF ",    // 3
   "AUTO",      // 4
   "SON ",      // 5     
   "SOFF",      // 6     
   " OFF  - "};  // 7 
   
     
   strcpy (G_strcpy_buf,  strings[msg_indx]); 
   strcpy (G_strcpy_buf,  strings[msg_indx]);  // possible compiler bug???, need to call strcpy twice 
   
   com_str_handler (0, usr_buf);  // common string handler to write or copy string to user buf
}


I have five similar routines and all behave the same way.

I am using 4.104.

Any suggestions appreciated. Thanks.

Lou
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jan 21, 2010 9:55 pm     Reply with quote

You didn't provide a test program, so I made one. The program below,
compiled with vs. 4.104 and running in the MPLAB simulator, produces the
following output in the Output Window:
Quote:

BGINT
BGEXT
BGBTH
BGOFF
AUTO
SON
SOFF
OFF -


Code:

#include <18F452.h>
#fuses XT,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

const char strings[][*] =
{
   "BGINT ",    // indx 0
   "BGEXT ",    // 1
   "BGBTH ",    // 2
   "BGOFF ",    // 3
   "AUTO",      // 4
   "SON ",      // 5     
   "SOFF",      // 6     
   " OFF  - "   // 7 
};

//======================================
void main(void)
{
int8 i;
char G_strcpy_buf[20];

for(i=0; i<8; i++)
   {
    strcpy(G_strcpy_buf, strings[i]); 
    printf(G_strcpy_buf);
    printf("\r");
   }

while(1);
}
Guest








PostPosted: Sat Jan 23, 2010 10:08 am     Reply with quote

Thanks PCM programmer.

A stand alone pgm works as expected. However, inside my application, it misbehaves. Having worked in a Unix environment, I am hesitant to suspect the compiler, but please take a look at these interesting symptoms:

I stated that 2 back-to back strcpy's inserted before the strcpy work but a single one gives me garbage strings. It turns out that the extra strcpy is not the key - a number of different statements inserted BEFORE a single strcpy cause the pgm to work.

I inserted 8 statement between the const string declaration and the strcpy that I can control at run time by changing variable SPEED_INDEX from 1 thru 8.

When SPEED_INDEX = 1, 2, 3, or 7, the inserted statement causes the pgm to work. The others have no effect.

What I think is happening is that the stack is in trouble when the strcpy is executed. Inserting certain statements BEFORE the strcpy (those that manipulate the stack?) perhaps somehow straighten out the stack by the time the strcpy is reached. I do not know how to prove this.

Another intersting point: If I temporarily replace the routine that uses
const char strings[][*]strings with a routine that uses a conventional (in ram) array of strings, the pgm works, which does not prove, but suggests, that the application has not messed up the stack. A conventional arraay of strings is not a feasible long term solution because of the huge amount of memory (rom and ram) that is used.

I know a stand-alone pgm would be helpful, but the problem only happens when running in the full application environment.

Thanks for any suggestions - this one has me stumped.

Regards,
loupan
Code:
 
        // Certain of the following statements, when executed
        // before the strcpy result in the program working
 
         if (SPEED_INDEX == 1) 
             printf ("\n\rstep 2, n=%u, msg_strings_lu=%lu, G_misc_msg_buf = '%s",
                           n, &msg_strings[n], G_misc_msg_buf);
                           
     
      if (SPEED_INDEX == 2) 
         printf ("\n\rstep 2, n=%u, msg_strings_lu=%lu, G_misc_msg_buf = '%s",
                           1, 10000, "hello");
                           
      if (SPEED_INDEX== 3) 
         printf ("\n\rhello world\n");
         
      if (SPEED_INDEX== 4) 
         printf ("\n\r");
         
      if (SPEED_INDEX== 5) 
          x1();
         
      if (SPEED_INDEX == 6) 
         x2(2);
         
      if (SPEED_INDEX== 7) 
         x3(5);
         
      if (SPEED_INDEX== 8) 
         a = x2(3);
         
      if (SPEED_INDEX== 9) 
         a = b;
       

//---------------------------------------------------------------

The routines used above
Code:

int x1 ()  {
   return 1;
}


int x2 (int val)  {
   return 1+val;
}

int x3 (int val)  {
   printf ("val=%u", val);
}


Code:

////////////////////////////////////////////////////////////////////////////
// bg_msg_loader - loads a constant msg into user buffer for bar graph messages

void bg_msg_loader (char *usr_buf, int msg_indx)  { 

   const char  strings[][*] =   {

   "BGINT ",    // indx 0
   "BGEXT ",    // 1
   "BGBTH ",    // 2
   "BGOFF ",    // 3
   "AUTO",      // 4
   "SON ",      // 5     
   "SOFF",      // 6     
   " OFF  - "};  // 7 
   
     
   strcpy (G_strcpy_buf,  strings[msg_indx]); 
   strcpy (G_strcpy_buf,  strings[msg_indx]);  // possible compiler bug???, need to call strcpy twice 
   
   com_str_handler (0, usr_buf);  // common string handler to write or copy string to user buf
}
Ttelmah
Guest







PostPosted: Sat Jan 23, 2010 3:27 pm     Reply with quote

The PIC, doesn't have a 'variable' stack, it only has a 'call' stack. If the stack was a problem, you'd be jumping to, or returning to the wrong location...
Post your com_str_handler code.
Are you sure that G_strcpy_buf, and usr_buf are large enough - have you allowed for the terminating character?.
Have you tried a simple delay?. All of your print functions take _time_. Strong possibility something in your buffer handling is recovering.

Best Wishes
Guest








PostPosted: Sat Jan 23, 2010 3:55 pm     Reply with quote

Ttelmah,

thanks for the response.

I replaced one of the "inserted" statements with a 1 second delay and the problem still occurs. I also tried substituting other builtins, such as atof, etc. The problem still occurs.

Since 2 back to back strcpy's work (one extra inserted strcpy), and the print related functions work, it seems like inserting a string function before the operational strcpy eliminates the problem.

com_str_handler is OK. I know this because I put some printf's in the routine that I posted, before and after the strcpy calls, and I can see the corrupted string at that point. In fact, I inadvertently removed the first strcpy (from the back-to-back strcpy's) and noticed that the code was still working. From experimenting, this was due the fact that the printf was still in place serving whatever function the strcpy was serving to "fix" things. That's when I realized that the first strcpy was not unique - but as I said, so far, it seems to be part of the pattern that string related functions seem to "fix" the problem. In summary, I seem to need a "sacrificial" string function before the operational strcpy for things to work. "Very strange behavior for a major appliance:)"

An other thoughts would be appreciated.

You and PCM are real assets to this forum.

Regards,

loupan
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Jan 24, 2010 12:10 pm     Reply with quote

Can you post a simple little test program that shows the problem ?
(Similar to what I posted, and compilable without errors).
loupan



Joined: 22 Oct 2007
Posts: 21

View user's profile Send private message

PostPosted: Sun Jan 24, 2010 1:43 pm     Reply with quote

A stand-alone program works. But when this routine is embedded in my rather large application, the problem occurs.

I have been using the double strcpy "temporarily" for over year while I wait for a response from CCS, and with the 2 strcpy's in place, the app works. As I mentioned earlier, a replacement of the [][*] strings with a arrray of strings:

Code:
char [] [] = {
         "hello world",
         " hello again",
           etc
}

works fine with a single strcpy loading the string into a global buffer, but this approach uses too much memory.

Since this only happens when embedded inside my application, are there are any tests you can think of that would shed light on the problem, I would appreciate it.

I did notice that when I tried to print out the adrs of msg_string[n] in a printf, the value returned was always the same regardless of the index. I know the compiler is using some special tricks with this construct to save space. But I found that a little strange.

I would hate to deploy this with a kludge workaraound not knowing why the workaround works.

Thanks again

loupan
loupan



Joined: 22 Oct 2007
Posts: 21

View user's profile Send private message

PostPosted: Mon Jan 25, 2010 5:46 pm     Reply with quote

Just to finalize this, the following if I call the following function before the strcpy, all works 100% in each of the 6 routines that make use of the variable len constant strings. It appears that this sacrificial function is cleaning up whatever is messed up by the time the strcpy is called.

Code:
///////////////////////////////////////////////////////////////////////////////////
// sacrificial_str_fcn - calls a sacrificial string function so that
// Variable constant strings work reliably

void sacrificial_str_fcn ()  {
   char junk_buf[15];
   
   sprintf (junk_buf, "hello world");
}
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group