LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

CVI Error: Over Array Bounds

When the attached C-File is compiled and executed in Debug mode CVI fails with an Over Array Bounds error while dereferencing a valid char * pointer. The function 'LogEnetData ()' is passed a pointer to over a thousand bytes of valid data and yet CVI declares an error when the loop index is 2.  I believe that this violates standard C behaviour.
 
When I single-stepped through the code and monitored the value of pData after it had been incremented, I got the following results:
 
          i                              pData
-------------------           -----------------
          0                        0x0012FA6D                        This is OK
          1                       "Over Array Bounds"         
0 Kudos
Message 1 of 12
(4,549 Views)
Hurst -
 
Here's what I think is happening.  Your data is an unsigned short (two bytes).  You're using a byte pointer.  The first time through the body of the for statement the pointer to the data points to the first byte of the unsigned short - the second iteration the pointer is to the second byte of the short, and the third time through the pointer "walks off" the end of the unsigned short and you get the runtime error.
 
As it turns out, there is a different semantic in C99 with regard to for statements, but this isn't revelant to your problem I don't think.  In C99 the for statement forms its own block scope.
 
Bob
0 Kudos
Message 2 of 12
(4,505 Views)

In main(), did you intend to pass a pointer to the Data member of your struct?

 

Thus:

LogEnetData (fp, Message.MsgSize, Message.Data);

rather than:

LogEnetData (fp, Message.MsgSize, (unsigned char *)&Message.CsciSource);

 

Note that Message.Data is of type (unsigned char *) so the cast is unnecessary, and the address-of operator ( & ) will change the type of the passed parameter to (pointer to unsigned char *), which will not work.

 

0 Kudos
Message 3 of 12
(4,484 Views)

There was no error in my original post, I wanted to bypass the first element since that was an internal house keeping variable that needed to be passed to LogEnetData ().

Hurst C.

0 Kudos
Message 4 of 12
(4,467 Views)
I'm not sure if I understood what the here promlem is. Instead of passing the data buffer, you are passing LogEnetData a pointer to Message.CsciSource, which is a 16 bit short. You are reading that short byte by byte so after 2 iterations user protection kicks in and gives you the error because you have gone past the 2 bytes.

As mentioned earlier in the post, perhaps you meant to pass the data field instead of CsciSource?

Bilal Durrani
NI
0 Kudos
Message 5 of 12
(4,462 Views)

I think the intent of the program is to effectively produce a dump of the entire structure (apart from the first, size word), not just the data field. So the pointer passed is indeed correct, as it points to the start of the area to be dumped. The problem was that CVI run-time protection did not realise that valid data extended beyond the first two bytes pointed to.

JR

0 Kudos
Message 6 of 12
(4,457 Views)

Thanks, that is it exactly!

My issue is with CVI. I passed in an unsigned char pointer to be able to dump the whole message struct (minus the length field) to a log file, only to have CVI post a fatal run-time error in Debug mode after two bytes and then terminate. The program runs correctly in Release mode (no errors). There is a blatant inconsistency here!

Hurst C.

0 Kudos
Message 7 of 12
(4,450 Views)

Hurst -

Can't you can dial back the level of runtime error checking to avoid the runtime array-bounds checking?  As I recall there are three levels available (in the build panel I think) and you can run the debug executable, still catch library errors with a popup, but avoid popping up for an apparent array bounds violation.

I'm also wondering what would happen if you defined a pointer to the struct, then cast that pointer to a pointer to unsigned char.  Maybe the CVI runtime error checking would then work.

 

Hayes

 

0 Kudos
Message 8 of 12
(4,435 Views)

As forerror reporting, I have tried bracketing this section of code with DisableBreakOnLibraryErrors () and EnableBreakOnLibraryErrors () to no avail.

Hurst C.

0 Kudos
Message 9 of 12
(4,409 Views)
I see the problem now.

The problem here is that the runtime size checking is kicking and is based on the initial pointer that was passed.
A way to get around this would be to disable runtime checking for the individual pointer by using this macro

#define DISABLE_RUNTIME_CHECKING(ptr)((ptr) = (void *) ((unsigned)(ptr)))   

...
static void LogEnetData (FILE *fp, int size, unsigned char data[])
{
   int i;
   unsigned char *pData = data;

   DISABLE_RUNTIME_CHECKING(pData);
...
}

See the help topic "Disabling Protection for Individual Pointer" in the CVI Help for more information. User protection is available for debug built applications only so you would #define this macro with a _CVI_DEBUG_

You can use SetBreakOnProtectionErrors(), since this is a user protection error and not a library error.

I hope this helps.

Message Edited by bilalD on 02-07-2006 09:39 AM

Bilal Durrani
NI
0 Kudos
Message 10 of 12
(4,407 Views)