Неявная внутренняя связь отличается от явной внутренней связи (статической)?

Сегодня я столкнулся с особенностью, которая, может быть, и не очень важна, но тем не менее меня озадачивает. Может быть, я просто неправильно понимаю С++.

Некоторые массивы внутри исходного файла указывают на строковые литералы, например:

const char* a[] = { "a", "b", "c" };
const char* b[] = { "d", "e"};
const char* c[] = { "f", "g"};

Ни один из этих массивов указателей никогда не используется каким-либо образом, кроме передачи в GetProcAddress для извлечения указателя функции из библиотеки (это неблокирующий динамический загрузчик функций OpenAL/EFX/capture и создатель/менеджер контекста).

В конце концов мне пришло в голову, что я, вероятно, должен объявить эти переменные как static const, поскольку они не нужны нигде за пределами этого самого файла .cpp, поэтому явное внутреннее связывание казалось уместным. В любом случае они должны иметь внутреннюю связь (ISO14882 3.5(3)), так что мы только ведем себя как добропорядочные граждане, явно указывая на то, что компилятор уже предполагает.

Выполнение этого невинного изменения привело к увеличению размера исполняемого файла на 512 байт. Не то чтобы дополнительные 512b действительно имели значение, просто казалось нелогичным, что одна и та же вещь приведет к другому коду. Поскольку static const устарело (ISO14882 7.3.1.1(2)), я также попробовал анонимное пространство имен с тем же результатом.

Глядя на исходный код ассемблера, видно, что явное внутреннее связывание (static или namespace{}) переместит строковые литералы в .rdata, а не .data, а строковые литералы чередуются с массивами указатель-строка-литерал вместо того, чтобы иметь все строки и все указатели. в одном блоке соответственно. В этом, вероятно, и заключается причина разного размера — очень вероятно, что при перетасовке данных из одного раздела в другой возникло ограничение размера раздела. Интересно, что все 3 вкуса по-разному искажают названия.

Теперь мне интересно: не ошибаюсь ли я, должны ли эти указатели не иметь внутреннюю связь?

Кроме того, в моем понимании const уже доступен только для чтения, насколько static const "более доступен только для чтения" (один входит в .rdata, а другой нет)?


person Damon    schedule 30.06.2011    source источник


Ответы (1)


Ваши массивы не объявлены const, следовательно, они также не являются неявно внутренней связью. У вас есть неконстантные массивы указателей на константу.

Тем не менее, я не знаю, почему это влияет на то, заканчиваются ли строки в .rdata или .data.

person Steve Jessop    schedule 30.06.2011
comment
Боже мой, конечно... какая глупая, очевидная моя ошибка. На самом деле, это должен быть const char* const a[], который тоже ведет себя так, как ожидалось (неявная внутренняя связь и идентичное искажение). Также имеет смысл, почему непостоянные указатели на литерал должны быть в .data, если массив не является константой. Только литералы, я не знаю... Я ожидаю, что они будут доступны только для чтения в любом случае. Тем не менее, отличный улов. - person Damon; 30.06.2011