Неявната вътрешна връзка не е същата като изричната вътрешна връзка (статична)?

Днес се натъкнах на една особеност, която, макар и не особено важна, все пак ме озадачи. Може би и аз просто не разбирам C++ правилно.

Някои масиви в изходен файл сочат към низови литерали, като така:

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

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

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

Извършването на тази невинна промяна доведе до увеличаване на размера на изпълнимия файл с 512 байта. Не като допълнителен 512b наистина има значение, но просто не изглеждаше логично точно същото нещо да доведе до различен код. Тъй като static const е отхвърлен (ISO14882 7.3.1.1(2)), опитах и ​​анонимно пространство от имена със същия резултат.

Разглеждането на изходния код на асемблера показва, че изричното вътрешно свързване (static или namespace{}) ще премести низовите литерали в .rdata, а не в .data, а низовите литерали се преплитат с масиви от указател към низов литерал, вместо да имат всички низове и всички указатели в един блок, респ. Тук вероятно се крие и причината за различния размер - много вероятно разместването на данни от една секция в друга е достигнало ограничение за размера на секцията. Интересното е, че и трите вкуса променят имената по различен начин.

Сега се чудя: Правя ли грешка, трябва ли тези указатели да не имат вътрешна връзка?

Освен това според моето разбиране const вече е само за четене, доколко static const е "повече само за четене" (едното влиза в .rdata, а другото не)?


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


Отговори (1)


Вашите масиви не са декларирани const, следователно те също не са имплицитно вътрешно свързване. Това, което имате, са неконстантни масиви от указатели към const.

Въпреки това, не знам защо това влияе върху това дали низовете завършват в .rdata или .data.

person Steve Jessop    schedule 30.06.2011
comment
О, боже, разбира се... каква глупава, очевидна моя грешка. Всъщност трябва да бъде const char* const a[], което също се държи както се очаква (имплицитно вътрешно свързване и има идентично изкривяване). Също така има смисъл защо неконстантните указатели към литерала ще бъдат в .data, ако масивът не е const. Само литералите, не знам... Във всеки случай бих очаквал те да са само за четене. Все пак отличен улов. - person Damon; 30.06.2011