Форум » Clipper » Unrecoverable error 37: Exclusive required » Ответить

Unrecoverable error 37: Exclusive required

p519446: hi all. clipper 5.2 + blinker 6.0 (также пробовал на 7.0) + ADS 6.11. После небольшой переделки в исходниках прога стала вдруг выдавать сабж на самом старте. The Hoples Pages (http://www.ghservices.com/gregh/clipper/ie52c.htm) говорят, что: -------------------------------------------------------------------------------- 37 Too many symbols in symbol table This error occurs with an application linked with Exospace. The application will terminate immediately upon start up. This is caused by CODE GENERATORS that generate an excessive amount of symbols. Action: Some suggestions to resolve the problem are: 1) Decrease that amount and/or reuse symbols, declare as local. 2) List .PRGs in .CLP files to compile fewer and larger .OBJ files. 3) Some visitors have reported that the problem went away after switching to Blinker or rebuilding the entire application and libraries See Also: "Compiling" chapter in the Programming and Utilities Guide and the "CA-Clipper Technical Specifications" appendix. ----------------------------------------------------------------------------- Но, во-первых, у меня НЕ Exospace, а блинкер. Во-вторых, следование вышеприведенному в Holmes Pages совету: "2) List .PRGs in .CLP files to compile fewer and larger .OBJ files. " - приводит сразу же к появлению ошибки компилятора "C3023 Too many labels" (что с опцией /m, что без неё). В-третьих, переделка исходника как раз имела целью уменьшить размер таблицы символов: везде, где можно, PRIVATE-переменные были заменены на LOCAL'ьные и, кроме того, через препроцессор все эти локальные переменные были объявлены как: local locarr[50] #define myVar1 locarr[ 1] #define myVar2 locarr[ 2] ... #define myVar50 locarr[50] Казалось бы, это изменение должно только положительно отразиться на exe-шнике ? Однако, он почему-то увеличился в размере (с 4'394 до 4'401 Kb) и, самое печальное, вообще теперь не загружается. Кто-нить сталкивался с этим ? Всем ответившим заранее спасибо.

Ответов - 12

p519446: ЗЫ. Самое "забавное", что при переброске нескольких функций из нового .prg-модуля (который был сегодня создан с целью "дробления" больших старых модулей) обратно в старый - всё прекратилось. В результате имею несколько больших старых модулей и один маленький новый. Как только в этот новый модуль что-то перебрасывается из старых модулей - возникает эта ошибка. Странно и грустно (от пребывания в этом тумане)...

p519446: ЗЫ-2 (22:00). Только что обнаружился еще один загадочный постулат: кажется, суммарное количество функций в приложении ограничено сверху каким-то числом. Во всяком случае, сейчас мои исходники находятся в таком состоянии, что я ** НЕ ** могу в них добавить больше ни одной функции (даже пустой, просто возвращающей число 0). ЗЫ-3 (23:10). Частичное опровержение предыдущего утверждения: макс число функций-"пустышек" в одном .prg эмпирически установлено равным 261. Далее вылезает ошибка компиляции "C3024 too many procs". Однако если создать, скажем, два дополнительных исходника и в каждый включить по 261 таких функций-"пустышек", то два соотв-щих .OBJ спокойно слинкуются и программа запустится нормально. То есть, получается, что добавить новые функции (даже пустышки) нельзя именно в тот набор .prg, который у меня сейчас есть. А создать новые .prg с такими пустышками - можно. Короче, загадочно всё и странно. Кто-нибудь может подсказать причину всего этого ?

p519446: Решение найдено (правда, вопросы остались). В общем, если в .LNK-скрипт вставить строку BLINKER INCREMENTAL OFF то 1) .exe запускается нормально, даже если добавить к нему 261*5 = 1305 функций-"пустышек" (проверять на большее число у меня не хватило терпения); 2) размер .exe-файла уменьшается с 4'400 Kb до 3'742 Kb. Что касается пункта 2), то тут всё понятно: блинкер при ВЫКЛЮЧЕННОМ incremental link'e упаковывает таблицу символов (удаляет из неё дублирующиеся имена) и, кроме того, не добавляет паддинги после каждой функции. Остались вопросы: 1) какое всё-таки максимальное число функций допускает blinker ? 2) почему при замене 50 private-переменных на один local array[50] размер .exe увеличивается ? Всем включившимся в дискуссию заранее спасибо.


Григорьев Владимир: p519446 пишет: 2) почему при замене 50 private-переменных на один local array[50] размер .exe увеличивается А как это было определено? Если просто создать пустые модули и сравнить их, каков будет результат? Например, PROC MAIN() PRIVATE V1, V2,... // 50 переменных RETURN и PROC MAIN() LOCAL aV[50] RETURN Мне почему-то казалось, что первый модуль будет иметь больший размер.

Pasha: p519446 пишет: Далее вылезает ошибка компиляции "C3024 too many procs". Однако если создать, скажем, два дополнительных исходника и в каждый включить по 261 таких функций-"пустышек", то два соотв-щих .OBJ спокойно слинкуются и программа запустится нормально. Я необнократно нарывался на это ограничение компилятора и боролся так же - рзбиением на 2 модуля. Правда есть еще ограничение - too many external references И иногда это решение приводит ко 2-му ограничению Т.е. перебрасяваю функцию из одного модуля в другой, и количество функций уменьшается, а внешних ссылок растет, и опять ошибка. Приходилось бороться другим способом Но это следствие фиксированных таблиц символов у компилятора, ничего тут не поделаешь С харбором про эти проблемя забыл

p519446: Григорьев Владимир пишет: А как это было определено? Если просто создать пустые модули и сравнить их, каков будет результат? Да, если создать два .prg с объявлениями 128 private-переменных в первом и заменой этих 128 переменных на элементы массива local v[128] во втором, то .exe-файл для первого .prg (который со 128 private-переменными) будет немного больше, чем у второго (1'005'696 vs 1'003'264 байт). Но у меня модули-то непустые, есс-но. И все эти переменные используются в выражениях. В общем, я не знаю причину, по которой после компоновки размер .exe увеличивается. К великому "щасью", проблема с unrecoverable error 37 ушла. До тех пор, пока размер сжатой таблицы символов не приблизится к некоторому потолку, про который я так ничего и не выяснил; где-то в Инете видел, что, дескать, она ограничена для 1 obj размером = 64К. Но у меня для самого большого .prg компилятор сообщает, что: "Code size 86850, Symbols 19472, Constants 32750" Если я правильно понимаю, то размер таблицы символов в нём = 19472 байта ? Но ведь это в три раза меньше 64Кб!

suv: почему при замене 50 private-переменных на один local array[50] размер .exe увеличивается ? При замене private на local-array будет происходить увеличение кода, потому что для обращения к локальному массиву требуется больше информации. Для доступа к private необходим номер переменной в таблице символов, а для доступа к local-array - номер переменной в стеке + номер элемента массива. Таким образом, сам код будет занимать больше места. Для примера: MyPriv := 1 // 3 байта - 1байт код операции + один операнд(адрес переменной) MyLoc[10] := 1 // 5 байт - 1байт код операции + 2 операнда(адрес переменной, номер элемента) в комментариях указаны размеры только того кода, который отличается (код записи загруженной на стек единицы в переменную) Беспокоится об увеличении кода не следует, в этом нет ничего плохого. Каждая функция компилируется в сегмент класса 'CODE' с именем=имени функции, то есть с уникальным именем. То есть procedure MyProc будет на ассемблере так: MYMAIN SEGMENT WORD 'CODE' PUBLIC MYMAIN Что это значит? Это значит, что общий код может занимать довольно много места, намного больше, чем 64К, потому что все сегменты имеют разное имя. (Хотя на одну функцию, конечно, будет действовать ограничение 64К И к нему легко подойти вплотную, если писать абы как) А значит на увеличение кода можно смело насрать. А вот выигрыш от замены private на local - есть. Потому что информацию об именах (private, имена процедур, полей, а так же и ЛОКАЛЬНЫХ переменных, если включена опция /b - информация для отладчика) компилятор размещает в сегмент с одним и тем же именем для всех исходников SYMBOLS SEGMENT PARA 'SYMBOLS' Значит при линкове все фрагменты этого сегмента из разных OBJ будут объединены в один сегмент, с ограничением 64Kb Резюмируя, можно сказать так - класс SYMBOLS - не резиновый, а вот класс CODE - резиновый. (Имеется в виду класс линковки). Замена private на local имеет смысл, если символов становится слишком много. вышеприведенному в Holmes Pages совету: "2) List .PRGs in .CLP files to compile fewer and larger .OBJ files. " - приводит сразу же к появлению ошибки компилятора "C3023 Too many labels" (что с опцией /m, что без неё). Опция /m приведет к тому, что встретив DO MYPROC компилятор будет искать MYPROC.PRG и откомпилировать в тот же OBJ. У тебя такого нет, насколько мне помнится. Следовательно /m в твоих условиях ни на что не влияет. макс число функций-"пустышек" в одном .prg эмпирически установлено равным 261. Далее вылезает ошибка компиляции "C3024 too many procs". Однако если создать, скажем, два дополнительных исходника и в каждый включить по 261 таких функций-"пустышек", то два соотв-щих .OBJ спокойно слинкуются и программа запустится нормально. То есть, получается, что добавить новые функции (даже пустышки) нельзя именно в тот набор .prg, который у меня сейчас есть. А создать новые .prg с такими пустышками - можно. Короче, загадочно всё и странно. Кто-нибудь может подсказать причину всего этого ? Эти ограничения не связаны с форматом OBJ. Они связаны, очевидно с тем, что программист который писал clipper.exe тупо объявил массив для имен PRG-процедур, этот массив имеет ограничение по размеру. Линковщик - программа серьезная)) на порядок серьезней, чем clipper.exe Не вижу никаких причин для линковщика НЕ линковать 261 процедуру из одного OBJ + 261 процедуру из другого OBJ 1) какое всё-таки максимальное число функций допускает blinker ? ))) По барабану. Линковщику насрать на твои имена. Он оперирует совсем другими понятиями. Он линкует и группирует сегменты и делает фиксап смещений. Все, что его волнует - чтобы сегменты, склееные из разных частей не вылезли за границы. Чтобы не было противоречий в именах, в типах, чтобы была точка входа, чтобы не было неопределенных ссылок, чтобы все фиксапы оффсетов могли быть выполнены и т.п. Ограничения скорей накладываются клиппер-машиной. Почему перестало запускаться - внятного ответа нет. Инкрементальная линковка бывает глючит. Возможно из-за этого. Помогла полная перелинковка - и славтегос.

suv: Ах, да..... Надеюсь, ты помнишь, что когда-то у меня твой EXE весом 3.5Мб прекрасно трансформировался в EXE весом в 1.5Мб. Ты там покумекай в этом направлении. Возможно жизнь проще станет. По поводу выравнивания. Мне что-то помнится, ты по телефону говорил какие-то жуткие цифры, но в посте я их не увидел. Если все же интересно - можешь спросить.

suv3: With symbol table compression enabled, i.e. with BLINKER INCREMENTAL OFF, this error should not occur at program start up, since all the duplicates have already been removed at link time. Забавно) Компилятор убирает дубли в пределах одного OBJ. Не знал, что блинкер умеет убирать дубли по EXE в целом. The maximum number of unique symbols remains 16384, however, so Blinker will display an error 1166 at link time if this limit is reached. Цифра кажется мне завышенной. Размер сегмента 65536 / 16 байт на имя = 4096 уникальных имен. Больше - не влезет, хоть тресни for i:=1 to 16000 ??chr(13),i &("M"+nTrim(i)):=1 next 3162 MAIN (23) Невосстановимая ошибка 668: Eval stack fault

suv3: ))) какие тут нахрен классы и ООП 8 классов по 50 методов))) В примере - переполняется не сегмент SYMBOLS, а runtime-таблица символов, но суть та же Можно попробовать слинковать EXE с 5000тыщ уникальными clipper-именами. Думаю, блинкер обосрется. Не от того, конечно, что ликовать не умеет. (Линкер выполняет вообще-то колоссальную работу. Одна таблица фиксап-оффсет на пару порядков больше) А от того, что клиппер так придуман, что размещает все имена в одном сегменте, а он не резиновый

suv3: Вот взял да сгенерировал 40 исходников в каждом из которых объявляется 250 уникальных имен (10тыщ имен). EXE слинковался но даже не запустился (ошибка 37). Почему - загадка. Ведь все слинковано. А функции, в которых создаются переменные - даже не запускаются. Вообще, фигню в хелпе пишут. Надо верить экспериментам и мапу (карта линковки) А в мапе написано - все данные в сегментах с одинаковым именем SYMBOL (используемые символические имена) НЕ объединяются в единый сегмент, как этого требуют правила линковки. Вместо этого они линкуются как разные сегменты с разными именами и одним классом линковки. То есть они идут друг за другом, а фиксап смещений не производится. Это значит, что в общем-то упомянуть во всех PRG различных имен можно довольно много. Больше, чем 4096, что и подтверждают прямые эксперименты. Сгенерировал 50 исходников с 100 именами в каждом (5000 имен) - все прекрасно. Больше, чем 4096 Но одновременно работать с больше чем 4096 именами по-любому не получится. Проверено на практике в различных вариантах. И в одной процедуре и в цепочке. Так же, как видим, существуют некие сложности неясного характера на общее кол-во упоминаемых переменных, причем столь существенные, что EXE не запускается. Устал думать на эту тему

p519446: suv3 пишет: Вот взял да сгенерировал 40 исходников в каждом из которых объявляется 250 уникальных имен (10тыщ имен). EXE слинковался но даже не запустился (ошибка 37). А ты использовал при линковке команду BLINKER INCREMENTAL OFF ?



полная версия страницы