инициализация карты: объектный код в 50 раз больше исходного кода - PullRequest
3 голосов
/ 11 ноября 2011

Я работаю в C ++ с BCC32.Я инициализировал карту примерно с 1000 записями, например:

extern map<string, string> city ;
void region_init_0 (void) { 
city["abc01"] = "Brussels" ;
city["xyz03"] = "Liege" ;
...
}

Длина файла .cpp составляет 40 КБ.После компиляции я получаю файл .obj размером 2,2 МБ.После связи с другими модулями .exe-файл также на 2 МБ длиннее, чем до того, как я добавил карту.Я не понимаю, почему я получаю это соотношение 50 между длиной объектного кода и общей длиной строк ASCII.

Как я могу уменьшить это?Я предполагаю, что должны быть более умные способы инициализации карты, которые будут оставаться постоянными во время выполнения программы.

Спасибо.

Ответы [ 4 ]

3 голосов
/ 11 ноября 2011

Вы включили оптимизации в своем компиляторе?

Возможно, вы могли бы иметь некоторый код, такой как

typedef std::pair<const char*,const char*> paircstr_t;
const paircstr_t initarr[] = {
  { "abc01", "Brussels" },
  { "xyz02", "Paris" },
  /// etc...
  { (const char*)0, (const char*)0 } // terminating null placeholder
};

extern map<string, string> city ;
void region_init_0 (void) { 
   for (int i = 0;; i++) {
      const char* curname = initarr[i].first;
      const char* curcity = initarr[i].second;
      if (!curname || !curcity) break;
      map[curname] = curcity;
   }
}

Размер кода объекта может быть меньше, но время выполненияразмер кучи не изменится.

2 голосов
/ 11 ноября 2011

Просто предположение: оператор [] встроен?Надеюсь, вы можете изменить это путем (не) определения некоторой константы препроцессора.Сборка релиза больше или меньше, чем отладка?

1 голос
/ 11 ноября 2011

Просто используйте внешнюю функцию и передайте ей необработанные строки:

extern std::map<std::string, std::string> city;

/* somehow make sure it cannot be inlined */
extern void AddCity(const char* const a, const char* const b) __attribute__((__noinline__));

void region_init_0 (void) {
    AddCity("abc01","Brussels");
    AddCity("xyz03","Liege");
    ...
}

extern void AddCity(const char* const a, const char* const b) {
    city[a] = b;
}

Я смоделировал ваш случай в моей системе, и он уменьшил размер исполняемого файла до 100 КБ (с удалением) с 924 КБ. Одно из отличий в симуляции заключается в том, что вы экспортируете больше строк, поэтому соотношение не будет равным.

1 голос
/ 11 ноября 2011

Вы добавили много кода.В объектном файле есть не только строки, но и сгенерированный код, и, возможно, отладочная информация (например, информация о номере строки) для каждой строки.Все это складывается.

Это также очень плохой способ инициализации карты;если это не сгенерированный машиной код, вы не хотите его писать.(И хотя, возможно, здесь нет проблемы, это означает, что карта не может быть const.) Более типичным решением для инициализации карты может быть что-то вроде:

struct MapInitializer
{
    typedef std::map<std::string, std::string> MapType

    char const* key;
    char const* value;
    operator MapType::value_type() const
    {
        return MapType::value_type(key, value);
    }
};

static MapInitializer initialValues[] =
{
    { "abc01", "Brussels" },
    { "xyz03", "Liege"    },
    //  ...
};

и затем:

std::map<std::string, std::string> city(
        std::begin( initialValues ), std::end( initialValues ) );

(Если инициализация должна быть отложена до более позднего вызова функции, тогда можно использовать:

city = std::map<std::string, std::string>(
        std::begin( initialValues ), std::end( initialValues ) );

. Но, как правило, если карта должна быть инициализирована с постоянной времени компиляциисписок, лучше всего сделать это в определении переменной, как указано выше.)

...