Jump to content

Enums losing their values (again)


Recommended Posts

Grrr... It's happening more often now.  I'm sure I've read about it here before but maybe it's time to table the issue again:

  • I'm working on a large project, and I'm running LV2012 32 and 64 bit on Windows.
  • I have an typedef enum inside a class. The enum happens to be the sole member of the class private data.
  • The enum is public and is used here and there all over my application
  • I decide to add another value to the enum and ... BAM! ... All instances throughout my project are reset to the first value of the enum.

Kind of defeats the purpose of the enum, don't you think?!

 

What do other people do? Define all enums fully during the design phase and never change them again? Label each instance of the enum with the desired value to provide some insurance against morphing? Don't use typedefs and update them all manually?

  • Like 1
Link to comment

This has happened to me often enough I'm paranoid about it. I think the use of it in a class is a red herring as I've seen my constants on the block diagram revert as well. I comment my constants now that way when it comes time to do a build, I can do a find all instances and "quickly" compare notes.

I've also stopped using enums in a lot of situations. I tend to have more very simple classes now...

Link to comment

Yeah. I guess empathy was what I was shooting for.  ;)



 I think almost all of the time I am adding new values to the end, not updating, or removing them, maybe this is safer since the constants already in my application aren't having their values changed.

 

There might very well be something in this. Today I added a value in the middle and I think I often do that when the morphing occurs.

Link to comment

The fundamental issue here is that Type definitions define type, not value.  Of course NI has been beating people over the head for more than a decade now to type def enums and clusters so it would be poor form if they turned around and gave you that answer when you complain about this behavior. 

 

Now NI, as is their wont, stretch the definition of 'Type' definition a bit and try to accommodate this expected use case.  This is as effective as the developers are in determining all of the corner cases.  LV users delve into some very dark corners, so this is usually hard.  Holes like this are likely bugs and probably get fixed in the usual (insert adjective here) timeframe.

 

We are used to the fact that it is safer to explicitly bundle type def constants instead of relying on the values of BD constants.  Maybe we should be doing the same thing here:


post-26690-0-05544400-1365699612.png

 

Which brings up another thing that bites you every so often when updating td enums connected to Case structures.  Sometimes a list 'a','c' gets silently changed to a range 'a'..'c'

 

post-26690-0-15275100-1365699717.png

Link to comment
... but I have a vague recollection that this had to do with compiled code separation

Yes - my compiled code is separated...

By the way, my current workaround for this is the old "pre-save, change, check, re-save" routine.

  • Pre-saving the project before making any changes is starting to become second nature before editing any enum typedefs.
  • Checking is a pain if you're paranoid, but usually I can tell if morphing has occurred by looking at any one instance. There seems to be an all-or-nothing pattern here...
  • If there is suspicion, then I have found that saving the enum and then reverting the entire project usually does the trick, i.e. the morphing seems to be an edit-time effect and generally does not occur if the project is re-opened with a modified enum. (At least, this is what I have seen when adding values or deleting unused values...)

Link to comment
Which brings up another thing that bites you every so often when updating td enums connected to Case structures.  Sometimes a list 'a','c' gets silently changed to a range 'a'..'c'

 

This is an appropriate place to link to the relevant idea, which has way too few votes - http://forums.ni.com/t5/LabVIEW-Idea-Exchange/Case-structure-prevent-automatic-change-from-selector-value-list/idi-p/1687284

Edited by Yair
Link to comment
  • 11 months later...

I'm using LabVIEW 2013SP1 and am running into a similar issue. My compiled code is NOT separated from my VIs.

 

I am trying to remove an Enum typedef (non-strict) from a class library. From the project window, I right-click on the typedef and select "Remove from library."

 

Every time I've done this, it causes ALL the typdef's BD constants to revert to the default "0" value. This is enormously problematic, obviously. Clearing the compiled object cache as suggested here does NOT resolve the problem. I'm forced to revert to the earlier copy on source code control. But it's vital that I am able to remove the enumerated constant to untangle some undesirable code dependencies.

 

Anyone have other troubleshooting suggestions?

Link to comment

What I've done in the past is open the typedef, right click on the icon to do a "find all instances", then document each constant's value with a comment (or really any means, comments are nice because you can do a #enum or something similar). Do what you need to to, then go back and double check your constants. Yes, it sucks, but I still don't trust LabVIEW as far as enums go.

Link to comment
What I've done in the past is open the typedef, right click on the icon to do a "find all instances", then document each constant's value with a comment (or really any means, comments are nice because you can do a #enum or something similar). Do what you need to to, then go back and double check your constants. Yes, it sucks, but I still don't trust LabVIEW as far as enums go.

Isn't it enough to open the typedef, and turn it into a ordinary control, apply changes, and then remove the typedef from the library?

 

/J

Link to comment
Isn't it enough to open the typedef, and turn it into a ordinary control, apply changes, and then remove the typedef from the library?

 

/J

 

You would lose the linkage to the typedef. Also I'm not sure how LabVIEW would handle changing the control from a typedef to a control, it may very well mutate your constant values just as modifying the typedef would.

 

Of course case structures completely throw a wrench in the plans I've mentioned above. Fun fun fun.

  • Like 1
Link to comment
You would lose the linkage to the typedef. Also I'm not sure how LabVIEW would handle changing the control from a typedef to a control, it may very well mutate your constant values just as modifying the typedef would.

 

Of course case structures completely throw a wrench in the plans I've mentioned above. Fun fun fun.

I thought that MikeL wanted to remove the connection to the typedef while preserving the constant values.

It is all about having fun ;-)

Link to comment

Somehow I was able to get the result I wanted by the following procedure / magical ritual:

 

  • Disconnected the typedef from the library.
  • Saved ONLY the Enum .ctl file.
  • Reopened the project, which now cannot find the .ctl file because it isn't part of the library as expected.
  • Pointed LabVIEW to the exact same file location for the .ctl file.
  • LabVIEW prompted me, warning me that there's a mismatch because the library was expecting the .ctl file to be part of the library, but the .ctl file wasn't expecting to be. Selected the option to resolve it in favor of disconnecting the .ctl from the library.
  • Waited for the entire project to load, then checked the ~155 instances of the enum throughout the project. Found that none had been reset.

Having to document every instance of the enum is sort of ridiculous. At that point, I think I'd rather use OpenG "select enum value by string name" primitive and implement Darin's "dare to dream" scenario. But that seems like it'd cause a ton of needless overhead...

  • Like 1
Link to comment

I guess I'm a little puzzled why some people see this and some people don't.  What is different?

I use strict typedefs quite frequently.  Quite often I place instances in class private data and constants fromt the typedefs in class methods.  Note that the .ctl files for the typedefs are in separate .lvlib files.

When I need to change a typedef I open it within the project, make modifications, apply the changes, and save.  I avoid things like renaming an item and inserting another item in the same step, which could obviously cause problems.  As long as I am careful in this respect, I don't (or haven't yet) encountered major issues.  Maybe I've just been lucky.  I'm puzzled what the difference is.

  • Like 1
Link to comment
I guess I'm a little puzzled why some people see this and some people don't. What is different?

I use strict typedefs quite frequently. Quite often I place instances in class private data and constants fromt the typedefs in class methods. Note that the .ctl files for the typedefs are in separate .lvlib files.

When I need to change a typedef I open it within the project, make modifications, apply the changes, and save. I avoid things like renaming an item and inserting another item in the same step, which could obviously cause problems. As long as I am careful in this respect, I don't (or haven't yet) encountered major issues. Maybe I've just been lucky. I'm puzzled what the difference is.

I too have never experienced it. But I remember Daklu writing an example (on lavag) to prove me wrong and that it does really happen.lol Maybe the Lavag historian can find it-I cannot currently

I vaguely remember that the reason that I never see it, is because my workflow is to have all the VIs in memory.

IIRC, when you change a typedef, the VIs not in memory are not updated,(of course) and so the change is not propagated., When they are next loaded labview isn't able to resolve the discrepancy and resets them to the zero value. LabVIEW is able to resolve the difference if the new value is at the end, but not in the middle. So I think I suggested having the old-style VI Tree just so that you could force LabVIEW to load all the VIs.

 

Since my workflow is to produce examples that act as regression test harnesses, the examples keep all the VI hierarchy in memory so I never see it.

Edited by ShaunR
Link to comment
  • 1 year later...
Hi there, I ran into this issue now. We should have used some other method for enumerating IO pins. Here are some results of my tests:

 

OK

Adding one or multiple items

Edit one or multiple items

 

Data corruption

Removing used items (constants of the removed value(s) change)

Edit and add combined (some or all constants in project change)

Edit and remove combined (some or all constants in project change)

Link to comment

I wonder if this can work:

  1. Open the typedef.
  2. Save the enum control somewhere.
  3. Replace the enum with a numeric.
  4. Apply the changes.
  5. Do your disconnecting.
  6. Replace the numeric with the enum you saved.
  7. Apply the changes.

A quick test indicates that replacing a an enum with a constant and a constant with an enum preserves the value, but I don't know if this applies when you do it with a typedef and I don't know if it will help with this specific issue even if it does work on typedefs. My guess would be no, because whatever's resetting the value will probably still happen at some point in this process, but that's just a guess.

Link to comment
  • 3 months later...

Thanks, Mike Le for your workaround - that did not quite work for me, but it did lead me to figure out how to resolve my instance of this problem.

 

We have an enum type def tucked away in a class. Actually - we have many. Like hundreds. We typically drop the type def on the BD and pass it in to a connector pane, or a shift register into a case statement, or.... Every now and then, some of the constants would revert to the 0'th element of the enumeration. 

 

What Mike suggested in this thread works - but I ran into two problems:

  1. When I added the type def back into the class, the problem came back.

  2. It does not help me identify which of the hundreds of places where I use enums are affected.

 

So, the solution (hopefully this will help you if you run into this) is gloriously simple. Clear the object cache! Go to Tools>Advanced>Clear Compiled Object Cache

 

Make's sense to me now.

 

This should be the second step in building an executable (the first being grabbing the sources from your repository).

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.