NS v2.2 compiler not checking for obvious errors?
jeffaco
Posts: 121
Hi,
I ran into a problem the other day that totally rendered my system useless until I was able to figure out the problem.
I have a buncha panels, and a buncha rooms. I have things set up where any panel can control any room, and the NetLinx master keeps state on what panel is set to what room. I have something like this:
DEFINE_CONSTANT
TP_COUNT = 5;
.
.
.
DEFINE_VARIABLE
char TP_ROOM[TP_COUNT] = {THEATRE, FAMILY, MASTER, GUEST, OFFICE};
Everything was fine and dandy. Then, for other reasons, I was reducing the number of panels from 5 to 4. But I forgot to change the initializers for TP_ROOM. So we're now initializing TP_ROOM with more values than it can hold.
The result: My system went nuts. It looks like the array was either not defined, or at least not defined such that my main program could change the values in the array. The end result is that my mainline code couldn't tell what room a panel was set for, and kept flipping back to the "Select a Room" page.
So, my question:
If I have something like:
DEFINE_CONSTANT
TP_COUNT = 4;
DEFINE_VARIABLE
char TP_ROOM[TP_COUNT] = {THEATRE, FAMILY, MASTER, GUEST, OFFICE};
why doesn't the NS v2.2 compiler report this with an error? This seems like a basic sort of thing that a compiler should do.
Sure, I can drop the automatic-style initializer and move it into DEFINE_START as assignment statements, but why?
Comments/thoughts appreciated.
-- Jeff
I ran into a problem the other day that totally rendered my system useless until I was able to figure out the problem.
I have a buncha panels, and a buncha rooms. I have things set up where any panel can control any room, and the NetLinx master keeps state on what panel is set to what room. I have something like this:
DEFINE_CONSTANT
TP_COUNT = 5;
.
.
.
DEFINE_VARIABLE
char TP_ROOM[TP_COUNT] = {THEATRE, FAMILY, MASTER, GUEST, OFFICE};
Everything was fine and dandy. Then, for other reasons, I was reducing the number of panels from 5 to 4. But I forgot to change the initializers for TP_ROOM. So we're now initializing TP_ROOM with more values than it can hold.
The result: My system went nuts. It looks like the array was either not defined, or at least not defined such that my main program could change the values in the array. The end result is that my mainline code couldn't tell what room a panel was set for, and kept flipping back to the "Select a Room" page.
So, my question:
If I have something like:
DEFINE_CONSTANT
TP_COUNT = 4;
DEFINE_VARIABLE
char TP_ROOM[TP_COUNT] = {THEATRE, FAMILY, MASTER, GUEST, OFFICE};
why doesn't the NS v2.2 compiler report this with an error? This seems like a basic sort of thing that a compiler should do.
Sure, I can drop the automatic-style initializer and move it into DEFINE_START as assignment statements, but why?
Comments/thoughts appreciated.
-- Jeff
0
Comments
Are those already defined as single byte constant, or a string or what?
If you are wanting an array of labels for your panel, shouldn't that be defined as
CHAR TP_ROOM[TP_COUNT][8] = {'THEATRE', 'FAMILY', 'MASTER', 'GUEST', 'OFFICE'};
// 8 being the maximum length of each "text string"
or was that supposed to be an integer array?
INTEGER TP_ROOM[TP_COUNT]={THEATRE,FAMILY,MASTER,GUEST,OFFICE}
// Where each element (IE: FAMILY) is pre-defined as a constant integer value as well in the DEFINE_CONSTANT section?
In both examples, as typed here, my Netlinx studio picked up on the problem when I set TP_COUNT to 4.
Starting NetLinx Compile - Version[2.2.0.108] [08-26-2004 18:01:52]
C:\Projects\test.axs
ERROR: C:\Projects\test.axs(33): C10583: Too many elements in initializer
ERROR: C:\Projects\test.axs(35): C10583: Too many elements in initializer
C:\Projects\test.axs - 2 error(s), 0 warning(s)
NetLinx Compile Complete [08-26-2004 18:01:52]
DEFINE_CONSTANT
char THEATRE = 1;
char MASTER = 2;
char FAMILY = 3;
You get the idea.
>In both examples, as typed here, my Netlinx studio picked
>up on the problem when I set TP_COUNT to 4.
Well, now that's interesting. That is NOT the case with my mainline program.
My mainline program is some 5000+ lines. And I use modules heavily. My total code (compiled) is in the area of 500k, as reported by the compiler.
Obviously, something in my code is confusing the compiler so that I don't get obvious warnings like this.
Any ideas why that might be?
-- Jeff
Instead of doing this:
char TP_ROOM[TP_COUNT] = {THEATRE, FAMILY, MASTER, GUEST, OFFICE};
Why not define it this way:
char TP_ROOM[] = {THEATRE, FAMILY, MASTER, GUEST, OFFICE};
And whenever you need to know how many rooms there are, you could use: MAX_LENGTH_ARRAY(TP_ROOM)
That way, it makes you have to go to the array definition to set the room assignment as well as the number of rooms. I realize this doesn't address why the compiler didn't report the error, but it does avoid running into that kind of problem.
So my question remains. That is: Obviously, something in my code is confusing the compiler so that I don't get obvious warnings like this. Any ideas why that might be?
-- Jeff
The software engineers at AMX provided this scheme of array assignment for several reasons, and the fact that you can get the size of the array can be very useful when an array is passed into a module for example. Then there is no need to pass the size of the array in as well, and there is no error when traversing arrays if you use the size that the compiler knows it to be.
Certainly when one is writing a driver, or any tightly repetitive deamon applet, that technique serves a purpose, but not in a NetLinx system. If you're concerned with that kind of response, you're using the wrong piece of equipment.
Okay, we agree to disagree. While your method would work, your method would also needlessly increase the size of the code and the speed of the code. In your specific example, the bug would be eliminated, but I can think of other examples where your approach would lead to all sorts of problems.
I agree that getting the length of an array is a very useful thing. And I do that many times in many modules that I've written. But doing it in the same module where you define it? Sure, you can do it, by why? (Particularly when you know what the length should be, and when you define it to have a particular length) As I said, we agree to disagree.
Let's get back to the crux of the issue here. The style of how to do it is simply a distraction.
The crux, as I see it:
1) The compiler doesn't reliably give warnings in the scenero that I specified. And, when the compiler doesn't give a warning or error:
2) The compiled code is just wrong. I believe that the compiled code has the array defined as zero length (or certainly less than either my defined size or the initializer size), causing my main program to absolutely malfunction with no indication as to why (since, when I try to assign values to array elements, it fails).
This kind of thing is a pain in the butt to debug. The program totally malfunctions with no indication as to why.
I like the NetLinx compiler a lot. But it's not perfect. This is just one of those imperfections ...
Thoughts and comments to the crux of the problem would be greatly appreciated, thanks.
-- Jeff
What is "around" your definitions? Anything else sharing a name with one of your variables/constants (even something non obvious like a module, an include,a program name)? Does explitely giving a type to the constant TP_COUNT help? Anything in the system log when you run the wrongly compiled thing? Any freaky char in the file? Did you try turning DEBUG on and trying to watch TP_ROOM? Did you try removing stuff from your program, one chunk at a time, until the compiler complains (i.e. trying to find the minimal set of conditions)?
Something is getting the compiler confused, that's for sure, since your program is not working. An acceptable behaviour would be to simply ignore the extra char (like a dynamic assignment would do).
Fred
Here's what I've trimmed stuff down to. In this example, I get no error, even though I have extra initializers for TP_ROOM. Try and run this (and reference TP_ROOM elements up to and including TP_COUNT), and unfortunate things happen.
(Actual program trimmed out, included as attachment in next message)
I downloaded your posted code and it generates a "Too many elements in initializer" error as expected when I tried to compile it. If I change tp_count to 6 then it compiles fine - as expected.
I've tried several things and haven't been able to to duplicate the error (of not reporting the error) that you are having.
My Netlinx Studio is V2.2 Build 83. When I asked for a web update I see that there is a newer version ready for download.
What build are you using?
Joe
I know this because a bunch of errors popped up in old code I had when I compiled in studio 2.2
The system I reproduced the problem on (and compiled my test code with) was running Studio v2.1. The system I originally encountered this with, I *thought*, was Studio v2.2, but now I no longer am so certain.
When Joe Hebert said he got compiler errors, I upgraded to the latest version of Studio and tried again. *I* got the errors this time. So I took my long involved mainline code (500k compiled), reduced TP_COUNT, and sure enough, I got a bunch of errors there too.
It looks like this was fixed in v2.2. Very cool.
So, being a pesky user that's never satisfied ;-), how about resolving the line number issues. I can easily reproduce knocking the line number off such that the compiler complains about a line that has no problem at all. You have enough of these, and when you get an error, it's "close" (but close is relative). In my case, "close" is often 15 lines off!
Comments on this issue?