Archived

This forum has been archived. Please start a new discussion on GitHub.

slice2cpp: member initialization in default constructor

Using Ice 3.2.0 on Linux RH3 and GCC 3.3.5, I've run into a problem related to the lack of member initialization in default constructors generated by the slice2cpp compiler. Attached is the test program; search for TODO to see what makes the test case succeed. Without explicit member initialization, the program throws the exception in AImpl::dispose() and valgrind says the following:

... Conditional jump or move depends on uninitialised value(s)
...

I'm not sure if this is a GCC compiler issue or not, but explicitly initializing the primitive member 'A::mFlags' solves the problem for me.

I have not tried to reproduce the problem with another compiler.

Comments

  • Not a bug, just a request for enhancement

    On closer examination it is obvious why the exception is thrown. The same memory region is being used for both objects and so the flag will be set unless the member is initialized to 0. I apologize for filing this as a bug.

    It might be useful to have an option in slice2cpp that would initialize all members, including those of built-in types, in the default constructor of a class. I have an example where I must pass many arguments to a class constructor, only one of which is really required to initialize a member of type
    ::Ice::Long
    
    . In this case I would prefer to have a class where the default constructor produces an object where the initial values of all members are well-defined. I also understand this is not how C++ is defined to work.

    Matthias
  • The problem with generating code that initializes such data members is that it incurs a performance penalty. Moreover, built-in types such as long are never initialized by C++ and doing so just for Slice types would be inconsistent with how C++ works.

    The performance penalty is potentially serious once you think about sequences of built-in types, or sequences of structs or classes containing built-in types. In that case, we'd end up initializing a lot of data that, most likely, would end up having the wrong value anyway.

    So, I think it unlikely that we'd add such initialization.

    Note that, for Slice classes, you can easily arrange for default initialization yourself (even for non-abstract classes). Simply register an object factory by calling Communicator::addObjectFactory. Now Ice, whenever it needs to create your class will call your object factory to instantiate the class. You can have the object factory either return a C++ class that is derived from the Slice-generated class, or (if the class is non-abstract), have the factory initialize the data members of the Slice-generated class before it returns the instance to the Ice run time.

    Section 6.14.5 in the manual gives you the run-down on this.

    Cheers,

    Michi.
  • Using factories to initialize members selectively

    Thanks for the response and advice, I'm basically doing what you suggest. The performance argument is a good one too, especially for aggregate members. Nonetheless, if an option were available in slice to annotate classes so their primitive members would be initialized by the default constructor (e.g. as they are in Java), I would use it.

    On a related note, I noticed that the generated constructor taking arguments to initialize all members has an initializer list which repeats the initialization of all inherited state at every level in the inhertiance hierarchy. Is this to guarantee a certain order of initialization?

    Matthias
  • ... I noticed that the generated constructor taking arguments to initialize all members has an initializer list which repeats the initialization of all inherited state at every level in the inhertiance hierarchy. Is this to guarantee a certain order of initialization?

    In C++, every virtual base class is constructed by the most derived class. The initialization lists in the constructors for each generated class need to include calls to the constructors for each virtual base class in order for the base classes to be properly constructed.

    Brent
  • mspycher wrote: »
    Nonetheless, if an option were available in slice to annotate classes so their primitive members would be initialized by the default constructor (e.g. as they are in Java), I would use it.

    One acid test for adding a feature to Ice is the question "Can the developer reasonably achieve what they want without the feature?" If so, the feature is unlikely to be added because it would amount to a convenience function.

    Of course, Ice does contain a number of convenience functions. But, when it does, they are for things that most developers want to do often (as opposed to things that a few developers want to do rarely). In other words, if demand for a convenience feature is big, that sometimes warrants adding the feature.

    The fundamental design tradeoff here is whether the added complexity for everyone is worth the added convenience for some developers.

    One of the appealing things of Ice is that it is simple and easy to learn and that, almost always, developers don't pay for what they don't use. Every feature we add makes APIs bigger and requires extra documentation. The documentation issue is serious because, usually, the extra feature means that the developer has to wade through more text about a topic to find what he or she needs, which adds extra friction. (Even if a feature is invisible at the API level (or Slice level) until it is needed, it becomes visible in the documentation.)

    You might want to read my recent article on API Design for more thoughts on the matter.
    On a related note, I noticed that the generated constructor taking arguments to initialize all members has an initializer list which repeats the initialization of all inherited state at every level in the inhertiance hierarchy.

    As Brent already pointed out, Slice classes support multiple inheritance which means we must use virtual C++ inheritance. But C++ requires all bases of a virtually derived class to be instantiated by the constructor of the most-derived class.

    Cheers,

    Michi.
  • Thanks

    Brent and Michi

    I appreciate the detailed response and understand where you're coming from regarding extensions to ICE/slice. No problem.

    Thank you also for clarifying the initialization of virtual bases.

    Cheers and have a good weekend.
    Matthias
  • michi wrote: »
    As Brent already pointed out, Slice classes support multiple inheritance which means we must use virtual C++ inheritance. But C++ requires all bases of a virtually derived class to be instantiated by the constructor of the most-derived class.

    Actually, I need to correct myself here. The main motivation for doing this is that to not do so would mean that you could have a partially-initialized class. The way it is, you are forced to initialize all members of the class, including the members of base classes, which makes partical initialization impossible.

    The reason Ice generates virtual inheritance for bases is so that you can use Slice class in multiple implementation inheritance without ending up with multiple copies of a base.

    Cheers,

    Michi.