views:

114

answers:

3

I have a large program with several large DLL's that are compiled with MFC and /clr. There is a limit of 65535 global FieldRVA entries in an assembly. If it is more the loader raises an exception. I already have Enable String Pooling (/GF).

I have alot of code like:

static char *pSTRING_ONE = "STRING_ONE";

if I compile witha macro such as:

#define pSTRING_ONE  "STRING_ONE"

it greatly reduces string for the CLR meta data so I compile but then I gain all of the problems of using a #define.

The question is: Is there another alternative to changing the static char * -> #define ?

A: 

From MSDN:

http://msdn.microsoft.com/en-us/library/s0s0asdt.aspx

"The /GF compiler option creates an addressable section for each unique string. And by default, an object file can contain up to 65,536 addressable sections. If your program contains more than 65,536 strings, use the /bigobj compiler option to create more sections."

Sounds like /bigobj is your friend here...

Bukes
Not sure that is the solution. It seems to be a problem with the number of entries in an assembly/DLL. The Exception is raised when trying to load the assembly/DLL at run time. Not compile time.
tgrantges
A: 

Instead of storing the strings in the data segment of your program (since you apparently have a TON of strings), much better is to have a resource file that contains them. Then just dynamically allocate a pool of strings and load the string resource file at program startup. This should totally eliminate the problem in question.

If that's not an option, assuming those are contained at file scope, why are you making the strings static? That's just the C way (and deprecated in C++) of saying "file scope only". const char *pSTRING_ONE = "STRING_ONE"; would create a global string shared across all the translation units. In this case beset is to just create one file that contains all the strings and then refer to them via extern declarations in a header.

What happens if you don't use /GF? From Bukes' answer it appears that by pooling strings you're causing the compiler to create one segment per string.

Mark B
I agree that in the long adjusting the code for these strings and variables (they are table field names and sizes) is the best long term approach. However, this legacy system has hundreds of fields spanning over a hundred tables and referenced from hundreds of source files.So I was looking for a quicker solution...
tgrantges
A: 

Unfortunately, the best solution to our problem was to include the offending code within a class.

// Old Way
static char *pSTRING_ONE = "STRING_ONE";

New

class CFieldDefs
{
  public:
     static char *pSTRING_ONE;
}

char *CFieldDefs::pSTRING_ONE = "STRING_ONE";

Usage:

CFieldDefs:pSTRING_ONE;

Even though the change was quite tedious, it greatly reduced the number of fieldRVA Entries CLR Fields within the DLL. Thanks for all your help.

tgrantges