Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. C# versus C++, null references and protecting against them

C# versus C++, null references and protecting against them

Scheduled Pinned Locked Moved C#
csharpc++
23 Posts 6 Posters 1 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Paul Michalik

    What you describe is Microsoft (implementation) specific version of "undefined behavior". The code in Foo is ill-formed and any assumptions about what happens after you took a reference to a "null" pointer are worthless...(the lang. spec. does not require an exception to be thrown.)

    C Offline
    C Offline
    Chuck OToole
    wrote on last edited by
    #21

    PS, it seems they've been arguing about this exact syntax for quite some time now. it appears there are two camps in the standard, one that wants it be defined behavior and one that does. The following like should provide some interesting reading on the subject. http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#232

    1 Reply Last reply
    0
    • C Chuck OToole

      I'm afraid you missed a subtle point in my example, the point that gets you into your function with a NULL value. I've simplified it below

      void Bar(CObArray &ar)
      {
      int foo = ar.GetCount();
      }

      void Foo(void)
      {
      CObArray *bob = NULL;

      Bar(\*bob);
      

      }

      set a breakpoint on the "int foo = ar.GetCount()" and observe that ar cannot be examined in the debugger, it's value is null. Note that you do in fact get to that statement, that is, the "Bar(*bob)" in the function "Foo" does not throw an exception. Although it looks like it is dereferencing the clearly null pointer, it's really just creating the argument for Bar by getting the address of the CObject and passing it, that is, making a "by reference" value for the Bar function. Therefore, the "crash" happens in "Bar" (i.e. your function) rather than at the invocation site. In my first reply, I was showing that the "ToBeAdded" object, which was valid, had a "Members" data member that was, in fact, NULL and that there was no "help" from the compiler / language rules that prevented it from passing NULL, even though the rules appear to say that's illegal. So, my conclusion was that if you don't want to allow NULL as an input to your functions and that you used to explicitly ASSERT / check for that case, you need to continue to check for that case because simply using "&" to eliminate that possibility was not going to work. Thus ends my rebuttal :)

      B Offline
      B Offline
      bob16972
      wrote on last edited by
      #22

      Ouch. I stand corrected. I started the day sure the sky was blue and now I'm left wondering if their implemetation ignores the statement "must be initialized by a valid object" and the part on page 198, section 8.5.3... "...Argument passing (5.2.2) and function value return (6.6.3) are initializations." But I agree (this includes some of your statements in another path of this thread as well), that I'm stuck with their implementation. I noticed they even let me dot off the invalid reference and call methods without any exceptions. At first I was shocked, but now I'm quite intrigued to see if any compiler vendor can implement this correctly. I'm glad I never had to go up against you in debate class. :) Excuse me while I go fix a million lines of active code. ;P

      P 1 Reply Last reply
      0
      • B bob16972

        Ouch. I stand corrected. I started the day sure the sky was blue and now I'm left wondering if their implemetation ignores the statement "must be initialized by a valid object" and the part on page 198, section 8.5.3... "...Argument passing (5.2.2) and function value return (6.6.3) are initializations." But I agree (this includes some of your statements in another path of this thread as well), that I'm stuck with their implementation. I noticed they even let me dot off the invalid reference and call methods without any exceptions. At first I was shocked, but now I'm quite intrigued to see if any compiler vendor can implement this correctly. I'm glad I never had to go up against you in debate class. :) Excuse me while I go fix a million lines of active code. ;P

        P Offline
        P Offline
        Paul Michalik
        wrote on last edited by
        #23

        Hm, not sure to whom this may concern, I always get confused by these hierarchies of threads... Anyway, the concept of a C++ reference is a subtle thing and it got even subtler with c++0x, as you might know. For good reasons this concept wasn't considered is what C# and other CLR targeting languages - and now we're back at OP's problem (at least as I see it...): in case of reference types (and in a verifiable program), you always deal with handles ("pointers") to instances. These handles can have two states: (a) pointing to valid object, (b) or "null". You can take a value of a "handle" by reference, by stating this intent explicitely at both call and target sites. However, this does not change the semantics of a handle, you just get access to the location of whatever the handle represents. So in C#, if you want to protect against handle pointing to "null", you either have to be explicit about that (code contracts are a great way to do that), or you rely on NullArgumentException handling (which is guaranteed to be thrown by the specs). The ref modifier mentioned somewhere in the thread does not help much:

        void Bar(MyClass pParam) {
        pParam.Member(); // guaranteed NullArgument exception if null
        }

        void Bar(ref MyClass pParam) {
        pParam.Member(); // guaranteed NullArgument exception if null
        pParam = new MyClass();
        }

        void Foo() {
        MyClass tI1;
        MyClass tI2 = null;
        MyClass tI3 = new MyClass();

        Bar(ref tI1); // error, tI1 uninitialized
        Bar(ref tI2); // ok
        Bar(ref tI3); // ok
        
        Bar(tI1); // warning or error, not sure
        Bar(tI2); // NullArgumentEx...
        Bar(tI3); // ok
        

        }

        1 Reply Last reply
        0
        Reply
        • Reply as topic
        Log in to reply
        • Oldest to Newest
        • Newest to Oldest
        • Most Votes


        • Login

        • Don't have an account? Register

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • World
        • Users
        • Groups