Pages: [1] 2   Go Down
Author Topic: strncpy() causes reset  (Read 1643 times)
0 Members and 1 Guest are viewing this topic.
New Jersey
Offline Offline
God Member
*****
Karma: 2
Posts: 535
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?

Code:
 
  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

Fort Lauderdale, FL
Offline Offline
Faraday Member
**
Karma: 71
Posts: 6144
Baldengineer
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Capacitor Expert By Day, Enginerd by night.  ||  Personal Blog: www.baldengineer.com  || Electronics Tutorials for Beginners:  www.addohms.c

West Des Moines, Iowa USA
Offline Offline
Sr. Member
****
Karma: 2
Posts: 428
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
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 Offline
God Member
*****
Karma: 2
Posts: 535
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Oops, I should have used:
Code:
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 Offline
Brattain Member
*****
Karma: 309
Posts: 26486
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 632
Posts: 50182
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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 Offline
God Member
*****
Karma: 2
Posts: 535
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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 Offline
Brattain Member
*****
Karma: 632
Posts: 50182
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
How do I do that?
Wouldn't that depend on where the "problem" is occurring? You haven't said.
Logged

New Jersey
Offline Offline
God Member
*****
Karma: 2
Posts: 535
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It looks like I'm running out of RAM.  I added a FreeMemory routine I found here: http://arduino.cc/playground/Code/AvailableMemory

Before 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.

* Water_Detector_Nanode_v6.ino (20.89 KB - downloaded 12 times.)
Logged

New Jersey
Offline Offline
God Member
*****
Karma: 2
Posts: 535
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 Offline
Brattain Member
*****
Karma: 632
Posts: 50182
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'll never understand why Microsoft invented a bunch of complex templates for casting, and why anyone uses them.

Code:
char *reply = (char *)(ether.tcpReply(session));

No templates; smaller footprint; easier (for me) to understand.
Logged

New Jersey
Offline Offline
God Member
*****
Karma: 2
Posts: 535
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'll never understand why Microsoft invented a bunch of complex templates for casting, and why anyone uses them.

Code:
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 Offline
Tesla Member
***
Karma: 74
Posts: 7253
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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 Offline
God Member
*****
Karma: 2
Posts: 535
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 Offline
Tesla Member
***
Karma: 74
Posts: 7253
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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 smiley
Logged


Pages: [1] 2   Go Up
Jump to: