String issue..

Status
Not open for further replies.

jim lee

Well-known member
Ran into an issue in my code where I (assume) I have a c string allocated on my stack but the instant I write to it everything crashes.

Simple sketch to show this..

Code:
int led = 13;

void setup() {
  Serial.begin(9600);
  while(!Serial);
  Serial.println("I'm here");
  Serial.flush();
  pinMode(led, OUTPUT);
  trash("123456");
  Serial.print("Still alive?!");Serial.flush();
}


void trash(char* inStr) {
  
  Serial.println("in trash");Serial.flush();
  inStr[0] = 'x';
  Serial.println(inStr);Serial.flush();
}


void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second

}


I swear this used to work. This code where the problem cropped up has been in there forever.. Well, I think its been in there forever. Anyway, has something changed? Or am I just going crazy and this has never been legal to do?

I put the blinking light in to show if the program survived or not.

Thanks!

-jim lee
 
Note: The first thing I would check is did you get any compiler warnings? I would strongly guess you would.

If you have not already done so, you should make sure that you are seeing all of the warnings.
Open up Preferences and make sure the Compiler warnings: All
is setup that way.

And sure enough it does complain:
Code:
yyy:9: warning: ISO C++ forbids converting a string constant to 'char*' 
   trash("123456");
The compiler probably allocated the string in code space (read only memory), which is fine, for you to do the call:
Serial.println("in trash");Serial.flush();

But doing: inStr[0] = ...
Will try to write to read only memory and fault....
 
I thought that it would only put things in read only memory if you did.. F("some stuff").

I see those warnings. Thousands of them. I've been ignoring them for years. First time I've been bit by them.

-jim lee
 
The F(“some stuff”) was needed on old and asthmatic MCUs with only little RAM to force string constants into the program flash memory.

Modern C++ compiler versions do most times not need such help. They optimize everything themselves, most times better as one can do by hand. By calling trash(“123456”), the compiler assumes that this is a string constant and puts it automatically in the program flash.
 
In the old "c" days was it put on the stack? Seeing as it was defined in a function call.

-jim lee
 
Yes, but still, even in old C (hey, I still code in C... :) ), one should not write to strings constants.
GCC < 4.0, for example, used to require the "-fwritable-strings" option to allow writing to string constants without throwing an error; nowadays I think it does not allow it at all.
 
Bleh! What a pain. I have to add a bunch of code to undo this error caused by compiler optimization.

Thanks for the info guys!

-jim lee
 
Interesting. I recompiled this same program for an Adafruit Feather and it worked fine.

Is there some compiler option that's allowing this on a Feather and not on a Teensy3.2?

-jim lee
 
It’s rather the compiler directives (makefile style) which come with the respective platform hardware folders into the Arduino IDE and which decide about the C++ version to use for a specific platform. Looks like Adafruit feather is using an older C++ version.
 
It’s rather the compiler directives (makefile style) which come with the respective platform hardware folders into the Arduino IDE and which decide about the C++ version to use for a specific platform. Looks like Adafruit feather is using an older C++ version.

Or just the linker file. Jim, can you post the one for Adafruit Feather ?
On the other hand, it's very weird to edit the linker file to fix a self-made bug... and why don't the use the flash for constants? That's not very RAM efficient!
 
The bug it long dead. I just added a dynamic buffer to the code that was calling it with the quoted string. It was just a surprise to me that it was optimized into a crash. I hate it when something that would work in c will no longer work in c++. Seems to break rules in my head.

@frank B : When "So long and thanks for all the fish" came out. I was living in the town where the end of the book took place in. I'd even eaten at the seafood restaurant he talked about. "Famous fish enterprise" I think was the name. I think highway 101 plowed through all that since then.

-jim lee
 
I'm confused about why you would do this in the first place. What is the expected result of attempting to change a literal constant?
 
The routine in question strips out un-dialable characters from a phone number string. So the resulting string is always shorter than the inputted one. All the strings either come from the user input or the SD drive so they are dynamically allocated. Hence no problem. The issue happened when debugging, to hurry things along when setting up a new set of contacts for the contact list on my phone, I hardcoded a bunch of stuff in there to give me something to test with. I EXPECTED them to be either on the stack or malloc-ed on the heap. Either way, shouldn't be an issue. But it wasn't the case.

-jim lee
 
Status
Not open for further replies.
Back
Top