01-20-2006 07:46 AM
01-20-2006 10:43 AM
LogEnetData (fp, Message.MsgSize, (unsigned char *)&Message.CsciSource);Message.CsciSource is declared as an unsigned short, which is why your loop would have problems after the first iteration.
01-20-2006 01:39 PM
The code runs without error when compiled in Release mode, so why does it yield a FATAL error in Debug mode?
I am casting the address to a char *, so why does CVI insist on treating it otherwise. This seems to be a GROSS violation of the C Standard. The function LogEnetData sees the data pointer as an unsigned char * and should treat it as such. Only the function main () really knows what this pointer really is. So, what you're telling me is that the LogEnetData function knows what is going on in main and bases its execution on that knowledge. As I said, this is a GROSS violation of the C Standard.
Hurst C.
01-20-2006 02:28 PM
It's not a question of the C standard; what you are seeing is the user protection CVI inserts in debug mode (to protect you from accessing invalid memory addresses, etc).
The simple fix to your problem is to change your call to LogEnetData like this:
LogEnetData (fp, Message.MsgSize, ((unsigned char *)&Message) + sizeof(int));
Since the object you are taking the address of is the entire struct, the pointer is passed with that context information and will not complain until you try to access outside of the struct bounds.
Admittedly, the fatal error you are seeing is not truly 'correct', but based on the context that it has to go on (address being passed is that of a 'short'), it is.
Alternatively, you can disable runtime checks from the Build Options dialog, which will prevent this error from happening.
Hope this helps,
-alex
01-20-2006 03:15 PM
I'm not interested in disabling runtime checks in the whole DLL just in this one section of code. I've tried using DisableBreakOnLibraryErrors () and EnableBreakOnLibraryErrors () around the loop but that doesn't help. Is there a clean way of just disabling the run-time checks for the loop?
I don't care how you sugar coat this anomaly, the fact remains that LogEnetData () receives a unsigned char * pointer and since there cannot be any alignment restrictions for a byte it violates the C Standard by treating it as anything else but an unsigned char *. This is exactly the purpose of a cast, to change the representaion of a variable. The observed behaviour in Release mode and Debug mode should be identical. The fact that a fatal error is elicited prevents the program from running to completion in Debug mode.
Hurst C.
01-20-2006 03:37 PM
10-23-2015 07:50 AM
This isn't done very well at all. Consider the following...
unsigned char _foo[] = {'F','O','O','D','F','E','E','D',0};
typedef struct { unsigned char _foo[8]; } foo_type;
union {
int num;
foo_type foo;
} _un = {'F','O','O','D','F','E','E','D',0};
foo_type _bar = {'F','O','O','D','F','E','E','D',0};
char* foo[] =
{
(char*)&_foo,(char*)&_bar, (char*)&_un,
};
You can NOT reference foo[2][1] but you can reference foo[1][1]. These are the same thing The union confuses the array checking Also since we are talking about array checking.. the initialized for _un shouldn't work at all since its passing in 9 values, instead of 8, but it compiles just fine..
To make things even worse you can reference foo[1][1000] and it works. Seems there is no bounds checking on the struct, but there is on the union, and its wrong. The array _foo does get the correct bounds of 9 btw.
By the way this can all be undone by casting back to some large array type.. say struct{ char foo[99999] };
The checking appears to (poorly) just look at the size of what got passed in. It sees the union as 1 item, while it sees foo_type an unknown quantity, and it sees _foo as 9