New Jersey
Offline
Sr. Member
Karma: 0
Posts: 375
|
 |
« on: April 16, 2012, 10:14:14 pm » |
I'm trying to take parse the HTTP reply I get from uploading data to pachube.com. I'm using EhterCard.h and it has a function tcpReply() that returns the HTTP response, which is HTTP/1.1 200 OK Date: Fri, 13 Apr 2012 12:17:36 GMT Content-Type: text/plain; charset=utf-8 Connection: close X-Pachube-Logging-Key: logging.Lo55opRx5dl5UwAw2NUO X-PachubeRequestId: 2ea1be6efb47aac0a0f47ec04196b14f721f605c Cache-Control: max-age=0 Content-Length: 1 Age: 0 Vary: Accept-Encoding
According to strlen() it's 308 bytes long. I want to use strtok (using \n as delimiter) to parse each line, but first I'm using strncpy() to prevent a a invalid conversion from 'const char*' to 'char*' But my sketch seems to be failing at the strncpy() function and reboots before I even get to strtok(). Below is my code, can anyone tell me what I am doing wrong? const char* reply = ether.tcpReply(session); // part of EtherCard.h library if (reply != 0) { char reply2[strlen(reply)+1]; strncpy(reply2, reply, sizeof(reply)); // I think Arduino is rebooting here reply2[strlen(reply)] = '\0'; char delims[] = "\n"; char *result = NULL; result = strtok( reply2, delims ); while( result != NULL ) { Serial.println(result); result = strtok( NULL, delims ); } }
|
|
|
|
|
Logged
|
|
|
|
|
Austin, TX
Offline
Faraday Member
Karma: 42
Posts: 5248
CMiYC
|
 |
« Reply #1 on: April 16, 2012, 10:19:31 pm » |
If reply is 308 bytes and reply2 is 309 bytes, that's 617 bytes of RAM for one operation.
Could you be running out of memory?
|
|
|
|
|
Logged
|
|
|
|
|
West Des Moines, Iowa USA
Offline
Sr. Member
Karma: 2
Posts: 429
|
 |
« Reply #2 on: April 16, 2012, 10:40:34 pm » |
const char* reply = ether.tcpReply(session); // part of EtherCard.h library Umm reply is a pointer to char, yes? sizeof(reply) will always be 2 on an Arduino! (It's not blowing up where you think it is. What does ether.tcpReply() return?) Edit: added conclusion.
|
|
|
|
« Last Edit: April 16, 2012, 10:52:32 pm by Morris Dovey »
|
Logged
|
There's always a better way!
|
|
|
|
New Jersey
Offline
Sr. Member
Karma: 0
Posts: 375
|
 |
« Reply #3 on: April 17, 2012, 12:26:06 am » |
Oops, I should have used: strncpy(reply2, reply, strlen(reply)) I made this change but it still reboots. I don't know about running out of memory. How do I tell? When I compile it says Binary Sketch: 18,082 bytes (of a 30,720 byte maximum)
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
UK
Offline
Brattain Member
Karma: 143
Posts: 19380
I don't think you connected the grounds, Dave.
|
 |
« Reply #4 on: April 17, 2012, 02:22:25 am » |
I don't know about running out of memory. How do I tell? When I compile it says Binary Sketch: 18,082 bytes (of a 30,720 byte maximum) That only reports program (flash) memory - the amount of SRAM used is not reported. My guess is that you have lots of strings consuming RAM. But without seeing code, it really is just a guess.
|
|
|
|
|
Logged
|
Pete, it's a fool looks for logic in the chambers of the human heart.
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 336
Posts: 36476
Seattle, WA USA
|
 |
« Reply #5 on: April 17, 2012, 05:37:17 am » |
I want to use strtok (using \n as delimiter) to parse each line, but first I'm using strncpy() to prevent a a invalid conversion from 'const char*' to 'char*' The proper cast would prevent the "problem" without the need to copy the string.
|
|
|
|
|
Logged
|
|
|
|
|
New Jersey
Offline
Sr. Member
Karma: 0
Posts: 375
|
 |
« Reply #6 on: April 17, 2012, 06:54:44 am » |
I want to use strtok (using \n as delimiter) to parse each line, but first I'm using strncpy() to prevent a a invalid conversion from 'const char*' to 'char*' The proper cast would prevent the "problem" without the need to copy the string. How do I do that?
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 336
Posts: 36476
Seattle, WA USA
|
 |
« Reply #7 on: April 17, 2012, 06:56:28 am » |
How do I do that? Wouldn't that depend on where the "problem" is occurring? You haven't said.
|
|
|
|
|
Logged
|
|
|
|
|
New Jersey
Offline
Sr. Member
Karma: 0
Posts: 375
|
 |
« Reply #8 on: April 17, 2012, 07:53:26 am » |
It looks like I'm running out of RAM. I added a FreeMemory routine I found here: http://arduino.cc/playground/Code/AvailableMemoryBefore I define reply2, I have less then 200 bytes. reply2 would be 308 bytes. I'd like not have to create reply2 and just use reply with strtok(), but reply is a const char and strtok() doesn't like that. So my solution is to strncpy reply to reply2. I think I'm running out of ram when I define reply2 on line 451. I would also like to free up some ram, but I'm not sure how to do that. Attached is the entire sketch, except for PachubeAPIKey.h which is just a #DEFINE with my API key (65 characters). I'm using a Nanode, which is similar to Arduino Deumilanove.
|
|
|
|
|
Logged
|
|
|
|
|
New Jersey
Offline
Sr. Member
Karma: 0
Posts: 375
|
 |
« Reply #9 on: April 17, 2012, 10:03:15 pm » |
I got it working. I shortened a bunch of strings in my Serial.print() statements and that freed up some RAM.
I also figured out how to cast my const char to char: char* reply = const_cast<char*> (ether.tcpReply(session));
I'm not changing the reply string, so I felt comfortable doing this.
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 336
Posts: 36476
Seattle, WA USA
|
 |
« Reply #10 on: April 18, 2012, 05:02:41 am » |
I'll never understand why Microsoft invented a bunch of complex templates for casting, and why anyone uses them. char *reply = (char *)(ether.tcpReply(session)); No templates; smaller footprint; easier (for me) to understand.
|
|
|
|
|
Logged
|
|
|
|
|
New Jersey
Offline
Sr. Member
Karma: 0
Posts: 375
|
 |
« Reply #11 on: April 18, 2012, 08:05:45 am » |
I'll never understand why Microsoft invented a bunch of complex templates for casting, and why anyone uses them. char *reply = (char *)(ether.tcpReply(session)); No templates; smaller footprint; easier (for me) to understand. I like your method better.
|
|
|
|
|
Logged
|
|
|
|
|
Central MN, USA
Offline
Faraday Member
Karma: 38
Posts: 6056
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
|
 |
« Reply #12 on: April 18, 2012, 08:49:31 am » |
You should move your Serial.print strings to PROGMEM.
A lazy way is to use the Serial.print(F("ahaqoihio")); Unless every output string is unique you are duplicating strings in PROGMEM.
|
|
|
|
|
Logged
|
|
|
|
|
New Jersey
Offline
Sr. Member
Karma: 0
Posts: 375
|
 |
« Reply #13 on: April 18, 2012, 11:40:53 am » |
You should move your Serial.print strings to PROGMEM.
A lazy way is to use the Serial.print(F("ahaqoihio")); Unless every output string is unique you are duplicating strings in PROGMEM.
I'm going to do that. I learned a lot about strings and RAM in trying to debug this problem.
|
|
|
|
|
Logged
|
|
|
|
|
Central MN, USA
Offline
Faraday Member
Karma: 38
Posts: 6056
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
|
 |
« Reply #14 on: April 18, 2012, 12:22:48 pm » |
If you do need a lot of strings even the PROGMEM can't hold, you can still get an EEPROM to store the strings. There's solutions to these problems 
|
|
|
|
|
Logged
|
|
|
|
|
|