2011-06-30 10 views
8

Dzisiaj spotkałem się z wyjątkową osobowością, która, choć prawdopodobnie nie jest tak ważna, jest dla mnie zagadką. Może po prostu nie rozumiem poprawnie C++.Niejawne powiązanie wewnętrzne nie jest tym samym, co jawne powiązanie wewnętrzne ("statyczne")?

Niektóre tablice wewnątrz punktu źródłowego pliku napisowych, tak:

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

Żaden z tych tablic wskaźnik jest zawsze wykorzystywane w żaden inny sposób niż były przekazywane do GetProcAddress pobierać wskaźnik funkcji z biblioteki (jest to nieblokująca dynamiczna ładowarka funkcji OpenAL/EFX/capture i twórca/menedżer kontekstu).

W końcu przyszło mi do głowy, że powinienem zadeklarować te zmienne jako static const, ponieważ nie są one potrzebne nigdzie poza tym plikiem .cpp, więc stworzenie wewnętrznego powiązania jawnego wydawało się odpowiednie. W każdym razie powinni oni mieć wewnętrzne powiązania (ISO14882 3.5 (3)), więc jesteśmy tylko dobrymi obywatelami, jasno określając, co kompilator już przyjmuje.

Dokonanie tej niewinnej zmiany spowodowało wzrost rozmiaru pliku wykonywalnego o 512 bajtów. Nie chodzi o dodatkowe 512b naprawdę ważne, ale po prostu nie wydawało się sensowne, że to samo spowoduje inny kod. Ponieważ static const jest przestarzałe (ISO14882 7.3.1.1 (2)), próbowałem również anonimowego obszaru nazw, z tym samym wynikiem.

Patrząc na źródła asemblera pokazuje, że wyraźne powiązania wewnętrzne (static lub namespace{}) ruszy literały ciągów w .rdata zamiast .data oraz literały łańcuchowe są przeplatane z wskaźnik do łańcucha-dosłownych tablic, zamiast wszystko łańcuchy i wszystkie wskaźniki w jednym bloku, odpowiednio. W tym przypadku prawdopodobnie leży przyczyna różnej wielkości - bardzo prawdopodobne jest, że losowe przenoszenie danych z jednej sekcji do drugiej spowodowało ograniczenie rozmiaru sekcji. Co ciekawe, wszystkie 3 smaki zupełnie inaczej opisują nazwy.

Teraz zastanawiam się: czy popełniam błąd, czy te wskaźniki: , czy mają wewnętrzne powiązania?

Ponadto, w moim rozumieniu const jest już tylko do odczytu, inhowfar jest static const "więcej tylko do odczytu" (jeden przechodzi w .rdata, a drugi nie)?

Odpowiedz

7

Twoje tablice są nie zadeklarowane jako const, dlatego też nie są wewnętrznie powiązaniami pośrednimi. To, co masz, to nie-stałe tablice wskaźników do stałych.

To powiedziawszy, nie wiem, dlaczego wpływa to na to, czy łańcuchy kończą się na .rdata lub .data.

+0

Och, oczywiście ... co za głupi, oczywisty błąd. Rzeczywiście, powinno to być 'const char * const a []', które również zachowuje się zgodnie z oczekiwaniami (niejawnie wewnętrzne powiązania i ma identyczne zniekształcanie). Ma również sens, dlaczego niestałe wskaźniki do literału byłyby w '.data', jeśli tablica nie jest stała. Po prostu literały, nie wiem ... Spodziewałbym się, że w każdym razie będą one tylko do odczytu. Nadal, doskonały połów. – Damon