Very interesting bug of Objective-C

When a member variable (aka property in SmallTalk term, semantically same to @property, but member variables are called “property” in SmallTalk. ) is accessed using self.<property name> through the @property mechanism or just <member variable> name, sometimes the result is different.

different values

4 responses to this post.

  1. This isn’t a bug the way I see it. Since a certain version of Xcode, clang automatically synthesizes variables – but by default clearPathControlOnDisable becomes _clearPathControlOnDisable, unless you use @synthesize clearPathControlOnDisable = clearPathControlOnDisable; – since you declare a ‘BOOL clearPathControlOnDisable’ in the interface, your instance should now really have two BOOL variables, one clearPathControlOnDisable and one _clearPathControlOnDisable.

    Hence self.clearPathControlOnDisable returns the _clearPathControlOnDisable (i.e. the property) and accessing just clearPathControlOnDisable returns your variable.

    Reply

    • Posted by jongampark on November 12, 2013 at 6:41 AM

      No, it’s not about declaring two variables.

      I remember this exactly because whenever Apple announced new version of Objective-C & runtime I paid attention to it even though they didn’t state they introduced new version.

      There were several versions so far.
      The very first Obj-C with properties as @property should not allow opting-out declaration of its corresponding member variable. At that time a member variable ( it’s fortunate and unfortunate at the same time because Apple picked @property. In SmallTalk terminology, member variable is property ) and a @property should be written altogether. The source code in the screenshot contained that kind of coding.

      2nd version started to allow dropping member variable declaration. At that time I remember that people kept asking in forums whether _variableName is kind of occupied by Apple or not. Previously, their documentation mentioned it may be used internally by Apple. So, they recommended not to use that. But it was not always like that. However, from the 2nd version of Objective-C which introduced @property, it became not clear.

      with the 3rd version or some version ( they didn’t say they changed Obj-C openly. However I noticed it because I kept testing on this. ), they started to write sampled code, especially in dealloc to use _variableName when the variable name is not declared.

      from 4th or 5th version, they started to allow opting out @synthesize. Then if the @synthesize is omitted they surely started to use _variableName. If not they used variableName. ( I have a recent post on this too. )

      Then there were more versions after that. 32bit Objective-C on Mac ( not iOS ) looks to be more outdated and Apple people don’t look to care much. For Obj-C, so-called modern one by Apple on iOS and Mac are different and didn’t make Mac version keep up with that of iOS version.

      There are somewhat different behavior after they supported more and geared toward x64 more. I didn’t test in depth after that version. I just follow how it is written on Apple’s doc. However, for the stuff before the fairly recent Obj-C, I tested them because I had interest in the small difference.

      So, the code above follows the first Obj-C with @property. It’s broken ( not always though. I didn’t test it sufficiently to say, “it’s always broken.”

      Reply

      • What you have written makes no sense. There is no bug; as the first responder noted the entirety of what you are showing simply demonstrates that the @synthesize automatically created for you declares the local variable with an “_”, which you have omitted; therefore when you use the property and use the instance variable you created you are using two wholly different variables.

        If you declared @synthesize clearPathControlOnDisable = clearPathControlOnDisable; (as the first poster noted) you would see exactly the same results between the two printouts would be identical, because they would refer to the same variable.

        Reply

        • Posted by jongampark on November 13, 2013 at 8:26 AM

          Hello, Mr. Gelner

          Due to your comment, I made sure if there was spelling difference between @property( assign ) BOOL clearPathControlOnDisable; line and the declaration of clearPathControlOnDisable line as a member variable. The spellings are the same. Then I think you didn’t use the very first version of Objective-C which had the @property introduced. At that time, you can’t just write @property… line without declaring a member variable for that.
          So, in other words, the very first Objectiv-C for that was like this :

          // in a header file
          @interface MyClass
          {
          BOOL isOK;
          }
          @property (assign) BOOL isOK;
          @end

          // In implmentation file
          @implementation MyClass
          @synthesize isOK;

          @end

          It still holds for backward compatibility. The “modern” Objective-C, which they call as such, only creates internal _variableName member variable for you automatically if you omit @synthesize line in its implementation file.
          If you put @synthesize isOK, you will be able to confirm that the automatically generated internal variable even with a “modern” Objective-C ( they called it Objective-C 2.0 before, but after they introduced some changes a couple of times, I noticed that they didn’t call it Objective-C 2.0 anymore. ) is variableName not _variableName.

          Can you follow me? There are couple of different Objective-C versions so far on this.
          For the very first version, you should declare a member variable, put @property line for that and put @synthesize for that.
          Then, for its following version, they started to allow opt-out declaring a member variable, but if you put @property line and @synthesize, they automatically generated internal variable as variableName.

          Then in a newer version, they started to allow omitting @synthesize line, then it creates _variableName automatically.

          The source lines shown in the screenshot is written for the very first version of Objective-C for which they introduced @property.

          Whenever a new version of Objective-C was announced ( actually whenever they announced new Xcode, because they didn’t really speak loudly that they increased the Objective-C version number ), I created sample projects and checked how things have been changed.
          Still, for Mac, somehow their 32bit part didn’t catch up that of iOS. Anyway Apple is dropping 32bit on Mac ( and probably soon for iOS ). So, I understand why they didn’t make 32bit behavior of Objective-C slightly catch up that of 64 bit ( 64bit is evolved to “modern” Objective-C ).
          Then it’s understandable if things are not broken.

          But things shown in the picture says that it’s somehow broken. I didn’t see this problem with any Mac project I’ve worked on so far.
          I even checked project settings ( because this project was not initiated from me ), but didn’t find anything strange.

          So, Mr. Gelner, I think you didn’t try to figure out slight difference between versions and the fact that they maintained the old behavior.
          I understand it. That is why I re-tested it a few months ago. Apple’s documentation is not really clear about that.
          But believe me. It looks to me that you are not familiar with the original behavior.

          Thanks for your comment, though. Somebody still reads my blog! :)

          Reply

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: