Hi Peeps,
I have something I don't really understand.
I'll post a code sample when I am back home but in the meantime, here what is happening...
I was playing around with my GPSr (Venus jobbie from Cool Components) and serial data.
I was using an event handler to read the data into a buffer (byte array) and convert it to a string. Very simple.
Odd thing comes in, I would constantly get out of memory errors while debugging. Not that often when it was doing debug.print (but still happened)
Array was static global array, I understand the serial.read will write to a buffer, not append, so it's not an issue there.
Solution was to lock the buffer, and in that block, read from serial and convert to string. Removing the lock would cause the problem to come back.
Is the event handler multi threaded? i.e. can many instances of it be called? I would not have thought so (it's a static method). This would explain why it blows up more while I am debugging...
Hopefully that all makes sense?
Cheers
Out of memory error
Started by Crispin, Sep 23 2010 08:46 AM
4 replies to this topic
#1
Posted 23 September 2010 - 08:46 AM
--
Take a seat, I'll be right with you.
Take a seat, I'll be right with you.
#2
Posted 23 September 2010 - 08:49 PM
plenty views and no replies
The sample here is not the most effecicient, reading one byte at a time but I'm playing still
Why would this throw an exception? I want to understand why it's not a good idea.
Some code:
Failed allocation for 17 blocks, 204 bytes
#### Exception System.OutOfMemoryException - CLR_E_OUT_OF_MEMORY (3) ####
#### Message:
#### System.Text.Encoding::.ctor [IP: 0004] ####
#### System.Text.UTF8Encoding::.ctor [IP: 0004] ####
#### System.Text.Encoding::get_UTF8 [IP: 0003] ####
#### GPS1.Program::spGPS_DataReceived [IP: 001f] ####
#### System.IO.Ports.SerialPort::DataEventHandler [IP: 0012] ####
Failed allocation for 13 blocks, 156 bytes
Failed allocation for 17 blocks, 204 bytes
Failed allocation for 17 blocks, 204 bytes
Failed allocation for 13 blocks, 156 bytes
Failed allocation for 13 blocks, 156 bytes
Failed allocation for 13 blocks, 156 bytes
Failed allocation for 13 blocks, 156 bytes
Failed allocation for 13 blocks, 156 bytes
Failed allocation for 13 blocks, 156 bytes
Failed allocation for 13 blocks, 156 bytes
Failed allocation for 13 blocks, 156 bytes
Failed allocation for 39 blocks, 468 bytes
Failed allocation for 39 blocks, 468 bytes
Failed allocation for 9 blocks, 108 bytes
Failed allocation for 9 blocks, 108 bytes
Failed allocation for 10 blocks, 120 bytes
Failed allocation for 10 blocks, 120 bytes
The sample here is not the most effecicient, reading one byte at a time but I'm playing still
Why would this throw an exception? I want to understand why it's not a good idea.
Some code:
static string rawNMEA = ""; static void spGPS_DataReceived(object sender, SerialDataReceivedEventArgs e) { byte[] buff = new byte[1]; try { lock (buff) { while (spGPS.BytesToRead > 0) { spGPS.Read(buff, 0, 1); string s = new string(Encoding.UTF8.GetChars(buff)); if (s == "\n" || s == "\r") { // parseNMEA(rawNMEA); rawNMEA = string.Empty; continue; } rawNMEA += s; } } } catch(Exception ex){ //if we get something we don't understand, restart everything. Debug.Print(ex.Message); rawNMEA = ""; } }
Failed allocation for 17 blocks, 204 bytes
#### Exception System.OutOfMemoryException - CLR_E_OUT_OF_MEMORY (3) ####
#### Message:
#### System.Text.Encoding::.ctor [IP: 0004] ####
#### System.Text.UTF8Encoding::.ctor [IP: 0004] ####
#### System.Text.Encoding::get_UTF8 [IP: 0003] ####
#### GPS1.Program::spGPS_DataReceived [IP: 001f] ####
#### System.IO.Ports.SerialPort::DataEventHandler [IP: 0012] ####
Failed allocation for 13 blocks, 156 bytes
Failed allocation for 17 blocks, 204 bytes
Failed allocation for 17 blocks, 204 bytes
Failed allocation for 13 blocks, 156 bytes
Failed allocation for 13 blocks, 156 bytes
Failed allocation for 13 blocks, 156 bytes
Failed allocation for 13 blocks, 156 bytes
Failed allocation for 13 blocks, 156 bytes
Failed allocation for 13 blocks, 156 bytes
Failed allocation for 13 blocks, 156 bytes
Failed allocation for 13 blocks, 156 bytes
Failed allocation for 39 blocks, 468 bytes
Failed allocation for 39 blocks, 468 bytes
Failed allocation for 9 blocks, 108 bytes
Failed allocation for 9 blocks, 108 bytes
Failed allocation for 10 blocks, 120 bytes
Failed allocation for 10 blocks, 120 bytes
--
Take a seat, I'll be right with you.
Take a seat, I'll be right with you.
#3
Posted 23 September 2010 - 10:45 PM
I think we'd need to see the rest of the code in order to find the problem. Can you post the complete source code?
Thanks,
~ David ~
~ David ~
#4
Posted 24 September 2010 - 12:06 AM
This may or may not be it...
1. buff is only allocated as one byte
2. Read is reading one byte, so far so good….
3. BUT GetChars will get bytes until it sees a terminating zero and who knows what is beyond the allocated one byte buff. :-(
A quick test fix would be to allocate two bytes for buff, and initialize buff[1] = 0;
#5
Posted 24 September 2010 - 07:29 AM
David - That's the code Only other bits are the serial port creation and event handler assignment in the main section. Nothing more :|
hari - I'll try your suggestion but it still seems odd. It works for a few seconds and then dies. GetChars converts an array of chars to string - an array is not ended by a null is it, but simply members in the array?
An update:
I stopped using the event handler and rather just a different thread in a loop. I am reading from a GPS device @9600 (BTW: Venus on rocks! Indoors, middle of brick house and I lock onto 12 satellites) which
has an update rate of 10Hz and spews out plenty (5 or 6 IIRC) sentences. Now, could it be that my event handler is just not quick enough for this? Increase baud rate? Not like there's much in my code to slow it down...
In the loop, I have while(datatoread>0) read 1 else sleep(10)/continue and this has run all night without a crash.
I wanted to use event handlers as it's "the proper" way to do it but seeing as this does not work (still debatable) and the data is so continuous, there is never really idle time, I see no reason I cannot keep it this way?
--
Take a seat, I'll be right with you.
Take a seat, I'll be right with you.
0 user(s) are reading this topic
0 members, 0 guests, 0 anonymous users