Serial Read Memory Corruption Error

Hi,

I am not sure if this is a code or hardware problem anymore, but I'm hoping someone will have some insight. Bear with me for the long explanation.

I have a Desktop with Hardy Heron (yes it has to be hardy heron sigh) for which I am writing code to read from a serial port. In this case, it opens the USB port. I have an IMU on the port that puts in data. I started trying this as an Orocos component and then as a separate program, and would like to move it back to Orocos, however, the memory error occurs in both cases.

The port is opened in a constructor ala:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//Configure and open the serial port here-set everything statically here (maybe change later to be user configurable)
	pname = COM1;			//May need an & here
	buffindex = 0;
	// Open the port
	if((fd = open (pname, O_RDWR | O_EXCL | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1)
	{
		//RTT::Logger::log() << RTT::Logger::Error << "[Serialinterface] rror with open() on port. Make sure exists." << RTT::Logger::endl;	
		return;
	}
	else
	{
		oldflags = fcntl(fd, F_GETFL, 0);
  		if (oldflags == -1) {
		status=GETFL_ERROR; 
		//RTT::Logger::log() << RTT::Logger::Error << "[Serialinterface] GET_FL Error: -2" << RTT::Logger::endl;
		return;}
    		oldflags |= O_NONBLOCK; //set the NONBLOCK flag //nonblocked
		if(fcntl(fd, F_SETFL, oldflags)==-1) {
		status=SETFL_ERROR; 
		//RTT::Logger::log() << RTT::Logger::Error << "[Serialinterface] SET_FL Error: -3" << RTT::Logger::endl;
		return;}
	}

	// Get the attributes
	if (tcgetattr( fd, &p_termios)==-1)
	{
	       close( fd );
	       return;
   	}



etc. etc. with the port settings. It has a Serial port read function or 2 ala:
1
2
3
4
5
6
7
8
9
10
11
int SSL::connieLogger::GrabData(uint8_t* buffer, int length)
{
	static bool neveragain = false;
	static uint8_t* recvbuf = new uint8_t[length];
	buffindex = 0;

	//printf("buf 0 \n");
	
	buffindex = ReadSerial(recvbuf,length);
	if(buffindex > 0){
		printf("BI %d \n", buffindex);}


which is intended to read a specific length of code. Tha read function occurs in:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int SSL::connieLogger::ReadSerial(uint8_t* buff, int length)
{
	// If you want to set delay between reads, set VMIN = number of bytes expected, VTIME=1 (100 ms wait), no FNDELAY
	bufptr = buff;

	nbytes=0;

	while (((nbytes = read(fd, bufptr, 1)) > 0) )//&& ((buff+length)>bufptr))
	{
		//printf("Bufptr: %d \n", *bufptr);
		bufptr += nbytes;
		
	}

	return (bufptr-buff); //return the number of characters read
}

where you can see I have commented out the specific length and just read whatever is on the port.

In the main function I have a while loop that calls the GrabData function until the user hits Ctrl-C to quit.

While the program is running, everything is fine. However, as soon as ctrl-c is hit, the following error occurs:

  +++ Caught exit request - shutting down ... 

*** glibc detected *** ./a.out: free(): invalid next size (fast): 0x0804e140 ***
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6[0xb7d76a85]
/lib/tls/i686/cmov/libc.so.6(cfree+0x90)[0xb7d7a4f0]
/usr/lib/libstdc++.so.6(_ZdlPv+0x21)[0xb7f42b11]
./a.out[0x804977b]
./a.out[0x80497a5]
./a.out[0x80497de]
./a.out[0x8049840]
./a.out[0x8049359]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe0)[0xb7d21450]
./a.out(__gxx_personality_v0+0x51)[0x8048cf1]
======= Memory map: ========
08048000-0804c000 r-xp 00000000 08:01 1820383    /home/


While the Orocos component is running, this happens every time there is data on the port. As a separate program, this only happens on quit. There are usually 496 bytes on the port. The buffer I am storing in is 2056 long.

The Valgrind program was recommended for debugging so I have that output:

==26063== Syscall param read(buf) points to unaddressable byte(s)
==26063==    at 0x40007F2: (within /lib/ld-2.7.so)
==26063==    by 0x804A4CF: SSL::connieLogger::GrabData(unsigned char*, int) (in /home/ndamore/Desktop/SerialTest/a.out)
==26063==    by 0x8049190: main (in /home/ndamore/Desktop/SerialTest/a.out)
==26063==  Address 0x42ad1b8 is 0 bytes after a block of size 2,056 alloc'd
==26063==    at 0x4022F14: operator new[](unsigned) (vg_replace_malloc.c:268)
==26063==    by 0x804A45B: SSL::connieLogger::GrabData(unsigned char*, int) (in /home/ndamore/Desktop/SerialTest/a.out)
==26063==    by 0x8049190: main (in /home/ndamore/Desktop/SerialTest/a.out)
BI 4464 

valgrind: m_mallocfree.c:210 (get_bszB_as_is): Assertion 'bszB_lo == bszB_hi' failed.
valgrind: Heap block lo/hi size mismatch: lo = 4294967295, hi = 72549442.
Probably caused by overrunning/underrunning a heap block's bounds.

==26063==    at 0x3801806D: report_and_quit (m_libcassert.c:140)
==26063==    by 0x38018361: vgPlain_assert_fail (m_libcassert.c:200)


I think it may be a hardware problem with how the USB port is setup and drivers or something, but I am not sure.

I should also note, that when I replace the read function with a set of fake data passed to the pointer, everything is fine. This seems to have something to do with the read function itself and I am stuck.

Suggestions would be much appreciated.
Thanks in advance.
I haven't read all the commentary, but did you really mean this?
 
static uint8_t* recvbuf = new uint8_t[length];
You don't preserve the length of the buffer as far as I can tell, but pass in different lengths each time. What happens if the length on subsequent calls is shorter than the length passed the first time? A buffer overrun.

The other function just uses that buffer, compounding the problem.
Topic archived. No new replies allowed.