Ограничение на размер идентификаторов в gnu ld

Модератор: Модераторы разделов

Аватара пользователя
savigm
Сообщения: 127
ОС: openSUSE

Ограничение на размер идентификаторов в gnu ld

Сообщение savigm »

Какие ограничения на имена идентификаторов накладывает компоновщик gnu ld?
В документации я про это ничего не нашел.
gcc не накладывает ограничений на локальные переменные, а вот ограничения на внешние переменные вроде определяются компоновщиком.
Спасибо сказали:
Аватара пользователя
savigm
Сообщения: 127
ОС: openSUSE

Re: Ограничение на размер идентификаторов в gnu ld

Сообщение savigm »

Эксперементировал с большими(около 100 символов) внешними именами, но ограничений так и не выявил. Скорее всего их просто нет в gnu ld.
Вопрос у меня изначально возник по причине чтения всем известной книги Бьерна Страуструпа "С++, язык программирования". В 4 главе наткнулся на простейшее упражнение (сложность 1 из 5 по книге):
Какой максимальной длины может быть внешнее имя в вашей системе?

Тут я сел. Документация по gcc гласит:
For internal names, all characters are significant. For external names, the number of significant characters are defined by the linker; for almost all targets, all characters are significant.

Т.е. локальные имена не ограничены по длине, а вот внешние определяются ограничениями компоновщика gnu ld. В документации по gnu ld я ничего по этому поводу не нашел. Т.е. такое простейшее упражнение, во всем известной книге, а мне с 3-х форумов пока ответов так и не дали, да и я потратил немало времени на выяснение ответа, и толком так его и не получил, только результат эксперемента.
Спасибо сказали:
Аватара пользователя
savigm
Сообщения: 127
ОС: openSUSE

Re: Ограничение на размер идентификаторов в gnu ld

Сообщение savigm »

Нашел книженцию по ссылке самого Бьерна Страуструпа на книжку:
C++ Solutions: Companion to the C++ Programming Language (3rd Edition) By David Vandevoorde, Bjarne Stroustrup

В ней решены большинство примеров, есть исходники в свободном доступе.
Так вот: ответ на то упражнение оказывается и рассчитан на эксперементальную программулину с длинным именем.

Вот иходник решения:

Код: Выделить всё

/* Code for exercise 4.6.
 |
 | "C++ Solutions--Companion to The C++ Programming Language, Third Edition"
 | by David Vandevoorde; Addison-Wesley 1998; ISBN 0-201-30965-3.
 |
 | Permission to use, copy, modify, distribute and sell this software
 | and its documentation for any purpose is hereby granted without fee.
 | The author makes no representations about the suitability of this
 | software for any purpose.  It is provided "as is" without express or
 | implied warranty.
 `----------------------------------------------------------------------*/

/*

This file may cause all sorts of problems for various compilers and
associated tools. Here is one message of a compiler that attempted
processing of this file. It speaks for itself:
   External symbol too long, truncated from 14328 to 4000 bytes,
   f__FP8DoublifyXT8DoublifyXT8DoublifyXT8DoublifyXT8DoublifyXT8DoublifyXT8Dou
   blifyXT8DoublifyXT8DoublifyXT8DoublifyXTdTd_T8Doublif...

*/

template<typename T, typename U>
struct Doublify {};
template<int N>
struct Exponential {
   typedef Doublify<typename Exponential<N-1>::LongType,
                    typename Exponential<N-1>::LongType>
           LongType;
};

template<>
struct Exponential<0> {
   typedef double LongType;
};

int f(Exponential<10>::LongType*) {
   return 3;
}


Общий смысл я понял, но детали как все это работает мне непонятны, если кто пояснит, буду признателен.
Хотя в тексте черным по белому сказано: в первую очередь смотрите ответ на вопрос в документации по компилятору и компоновщику, вот здесь-то и косяк - в доках по компоновщику gnu ld про это ни слова.

Вообще решения довольно непростые для таких несложных глав.
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Ограничение на размер идентификаторов в gnu ld

Сообщение NickLion »

savigm писал(а):
29.11.2009 04:12
Общий смысл я понял, но детали как все это работает мне непонятны, если кто пояснит, буду признателен.

Ну, рассмотрим Exponential<3>::LongType:
Exponential<3> - N == 0 ? нет, значит берем стандартное описание
struct Exponential<3> { typedef Doublify<typename Exponential<2>::LongType, typename Exponential<2>::LongType> LongType; }::LongType;

Exponential<2> - N == 0 ? нет, берем стандартное описание
struct Exponential<3> { typedef Doublify<typename struct Exponential<2> { typedef Doublify<typename Exponential<1>::LongType, typename Exponential<1>::LongType> LongType; }::LongType, typename struct Exponential<2> { typedef Doublify<typename Exponential<1>::LongType, typename Exponential<1>::LongType> LongType; }::LongType> LongType; }::LongType;

Exponential<1> - N == 0 ? нет, берем стандартное описание
struct Exponential<3> { typedef Doublify<typename struct Exponential<2> { typedef Doublify<typename struct Exponential<1> { typedef Doublify<typename Exponential<0>::LongType, typename Exponential<0>::LongType> LongType; }::LongType, typename struct Exponential<1> { typedef Doublify<typename Exponential<0>::LongType, typename Exponential<0>::LongType> LongType; }::LongType> LongType; }::LongType, typename struct Exponential<2> { typedef Doublify<typename struct Exponential<1> { typedef Doublify<typename Exponential<0>::LongType, typename Exponential<0>::LongType> LongType; }::LongType, typename struct Exponential<1> { typedef Doublify<typename Exponential<0>::LongType, typename Exponential<0>::LongType> LongType; }::LongType> LongType; }::LongType> LongType; }::LongType;

Exponential<0> - N == 0 ? да, теперь берем второе описание для конкретного числа
struct Exponential<3> { typedef Doublify<typename struct Exponential<2> { typedef Doublify<typename struct Exponential<1> { typedef Doublify<typename struct Exponential<0> { typedef double LongType;}::LongType, typename struct Exponential<0> { typedef double LongType;}::LongType> LongType; }::LongType, typename struct Exponential<1> { typedef Doublify<typename struct Exponential<0> { typedef double LongType;}::LongType, typename struct Exponential<0> { typedef double LongType;}::LongType> LongType; }::LongType> LongType; }::LongType, typename struct Exponential<2> { typedef Doublify<typename struct Exponential<1> { typedef Doublify<typename struct Exponential<0> { typedef double LongType;}::LongType, typename struct Exponential<0> { typedef double LongType;}::LongType> LongType; }::LongType, typename struct Exponential<1> { typedef Doublify<typename struct Exponential<0> { typedef double LongType;}::LongType, typename struct Exponential<0> { typedef double LongType;}::LongType> LongType; }::LongType> LongType; }::LongType> LongType; }::LongType;

Ну, и подстановка конкретных значений:
Exponential<3>::LongType == Doublify<Doublify<Doublify<double, double>, Doublify<double, double> >, Doublify<Doublify<double, double>, Doublify<double, double> > >
Вот так. Ну, а для 10 - 1024 будет только double... что дает очень немаленькое имя типа :)
Спасибо сказали:
Аватара пользователя
savigm
Сообщения: 127
ОС: openSUSE

Re: Ограничение на размер идентификаторов в gnu ld

Сообщение savigm »

NickLion, Спасибо конечно, но я почти ничего не понял, можно в двух словах, что делается?
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Ограничение на размер идентификаторов в gnu ld

Сообщение NickLion »

Не, в двух словах не получится...

Exponential объявлено в двух ипостасях - для произвольного целого значения N и для целого 0.
Для 0 определено как структура, содержащая описание типа LongType == double.
Для произвольного N тип с таким же именем объявлен как Doublify< тип LongType для Exponential с N-1, тип LongType для Exponential с N-1 >.
Т.е. получается рекурсия типа Doublify, причем получается 2 в степени N.

Так понятнее?
Спасибо сказали: