开发者

Static const initialization iPhone/Release

开发者 https://www.devze.com 2023-01-06 13:51 出处:网络
I have a cross platform library that has strange problem only on iPhone and only under release. // .h class cColor

I have a cross platform library that has strange problem only on iPhone and only under release.

// .h
class cColor 
{
public:
   static const cColor Red;
   static const cColor Green;
   static const cColor Blue;

   u8 r;
   u8 g;
   u8 b;
   u8 a;

   inline cColor(...) : ... { }
};

// .cpp
const cColor cColor::Red(0xFF, 0x00, 0x00);
const cColor cColo开发者_开发问答r::Green(0x00, 0xFF, 0x00);
const cColor cColor::Blue(0x00, 0x00, 0xFF);

It does look like an initialization order fiasco but the problem is not in a static method but later in the program. All cColor::Red, Green, Blue are set to 0. Actually I put some printf inside the constructor's { } and it doesn't print anything but maybe it is OK since it's during globals initialization.

Now the worst part: The library was working in Release as well till recently before I added a few functions (200-300 lines) Objective-C code that doesn't even get executed. Just by cutting from the code size I can fix the issue but that is not really option for me. Also the application is not that big, memory can't be the problem.

Btw cColor is included in precompiled header in the library and later in the application that uses the library.

Help! I'm really out of ideas.


Edited: Here is more info...

I moved only the initialization code from the library to my application and now the constants are getting initialized correctly.

I really think that the linker is messing up something.

Any ideas?


You can easily prevent a static initialization order fiasco: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.15

// .h
class cColor 
{
public:
   static const cColor& Red();
   static const cColor& Green();
   static const cColor& Blue();

   u8 r;
   u8 g;
   u8 b;
   u8 a;

   inline cColor(...) : ... { }
};

// .cpp
const cColor& cColor::Red() {
   static cColor* redColor = new Color(0xFF, 0x00, 0x00);
   return *redColor;
};

/* etc */

I don't know if it helps with your symptoms though.


This is a common case with static inits inside a library. Code with static initialization must be linked into the main application. A library is simply a collection of .o files, and at link time, the linker selects which .o files it wants to include into the final executable. If your main application does not reference those variables, the linker determines that the object code is unused and so the .o don't get pulled in and hence, the initializers don't initialize. A quick test is to reference them in your main exe sources (not in your library) or try the -Wl,-whole-archive or -force_load flag to gcc to force all the .o objects from your library to be included.


I'm convinced that this is a linker bug. I just found a work around which is really stupid. I moved one inlined function from the cColor class to the cColor.cpp. I had nothing else in the cColor.cpp except the static const initialization.

My guess is that because nothing else is in the translation unit in some cases the linker decides to ignore it.

I might send this to apple to see what they think about it.

P.S. Just to make it clear my initial tought was that this is memory corruption but I don't have any static memory allocations in my library/application. Also I have tested the code with multiple memory manager with different debug functions and the code is even leaks free.

0

精彩评论

暂无评论...
验证码 换一张
取 消