F
Fredrik Eriksson
(cross "posted" from Stackoverflow)
A while ago we had this declaration (simplified):
Declaration 1
struct SomeType
{
// allocates Implementation in SomeType's TU
SomeType();
// ... other stuff
struct Implementation
{
std::string someAtribute1;
std::string someAtribute2;
}
std::auto_ptr< Implementation> pimpl;
};
Some time later we changed de declaration to this (simplified):
Declaration 2
class OtherNameImplementation;
struct SomeType
{
// allocates OtherNameImplementation in SomeType's TU
SomeType();
// ... other stuff
std::auto_ptr< OtherNameImplementation> pimpl;
};
Where `OtherNameImplementation` is defined in `SomeType`'s TU, and has the exact same definition as `SomeType::Implementation` had (in Declaration 1).
Somehow we missed that `SomeType` has no defined destructor, hence the compiler generated destructor is defined in the user's TU.
The question:
For TU's that has been compiled against 'Declaration 1' Is there any form of guarantees that the behavior is "correct" when, in runtime, it uses 'Declaration 2'. Standard, implementation guarantees, I'll take anything
There is two reasons that I can think of, that it at least seems to 'work':
1. The compiler generated destructor should do the "right thing" since the memory layout is the same for both the Implementation-types, even though the type's name has changed.
2. We haven't noticed any implications during our Test period (there are several hundreds of applications that has this dependency)
Our target platform is Solaris, and we use Sunstudio 12.
Somehow we missed this during code review, and I assume this is at least UB, and in a perfect world we would define a destructor for `SomeType` and recompile every TU that is dependent of this.
A while ago we had this declaration (simplified):
Declaration 1
struct SomeType
{
// allocates Implementation in SomeType's TU
SomeType();
// ... other stuff
struct Implementation
{
std::string someAtribute1;
std::string someAtribute2;
}
std::auto_ptr< Implementation> pimpl;
};
Some time later we changed de declaration to this (simplified):
Declaration 2
class OtherNameImplementation;
struct SomeType
{
// allocates OtherNameImplementation in SomeType's TU
SomeType();
// ... other stuff
std::auto_ptr< OtherNameImplementation> pimpl;
};
Where `OtherNameImplementation` is defined in `SomeType`'s TU, and has the exact same definition as `SomeType::Implementation` had (in Declaration 1).
Somehow we missed that `SomeType` has no defined destructor, hence the compiler generated destructor is defined in the user's TU.
The question:
For TU's that has been compiled against 'Declaration 1' Is there any form of guarantees that the behavior is "correct" when, in runtime, it uses 'Declaration 2'. Standard, implementation guarantees, I'll take anything
There is two reasons that I can think of, that it at least seems to 'work':
1. The compiler generated destructor should do the "right thing" since the memory layout is the same for both the Implementation-types, even though the type's name has changed.
2. We haven't noticed any implications during our Test period (there are several hundreds of applications that has this dependency)
Our target platform is Solaris, and we use Sunstudio 12.
Somehow we missed this during code review, and I assume this is at least UB, and in a perfect world we would define a destructor for `SomeType` and recompile every TU that is dependent of this.