On-line: SergKis, Aleksandr_D, гостей 1. Всего: 3 [подробнее..]
АвторСообщение



Пост N: 1
Зарегистрирован: 07.11.11
ссылка на сообщение  Отправлено: 07.11.11 11:02. Заголовок: Ошибка DBSETLOC(0)


Провожу пересчет по всем полям в базе. При достижении определенного номера выскакивает ошибка:
DBSETLOC(0) Невосстановимая ошибка 667: Переполнение стека вычисления.
Кто-нибудь сталкивался с такой проблемой? Подскажите, что можно сделать?

Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 5 [только новые]


администратор




Пост N: 2186
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 07.11.11 11:11. Заголовок: Может это поможет ht..


Может это поможет
http://clipper.borda.ru/?1-0-0-00000350-000-0-0

Спасибо: 0 
ПрофильЦитата Ответить



Пост N: 2
Зарегистрирован: 07.11.11
ссылка на сообщение  Отправлено: 08.11.11 12:29. Заголовок: Спасибо за совет! Но..


Спасибо за совет! Но, к сожалению, ни разу не пользовался Blinker.

Спасибо: 0 
ПрофильЦитата Ответить



Пост N: 20
Зарегистрирован: 11.10.11
ссылка на сообщение  Отправлено: 12.11.11 19:24. Заголовок: pirat пишет: Провож..


pirat пишет:

 цитата:
Провожу пересчет по всем полям в базе. При достижении определенного номера выскакивает ошибка:
DBSETLOC(0) Невосстановимая ошибка 667: Переполнение стека вычисления.
Кто-нибудь сталкивался с такой проблемой? Подскажите, что можно сделать?



Переполнение стека - это переполнение стека Clipper. То есть это означает, что у вас возможно в какой-нибудь функции или выражении указано слишком много публичных или приватных переменных, параметорв функций, полей базы данных. Кроме того у вас могут быть много массивов или символьных строк.

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

Попробуйте уменьшить глубину цепочек вызовов функций, а также количество переменных и массивов. Если у вас много публичных или приватных переменных, то лучше их заменить локальными переменными, так как все публичные и приватные переменные занимают место в специальной таблице Clipper с определениями этих переменных.

Спасибо: 0 
ПрофильЦитата Ответить



Пост N: 21
Зарегистрирован: 11.10.11
ссылка на сообщение  Отправлено: 13.11.11 19:40. Заголовок: Чтобы вы располагали..


Чтобы вы располагали более полной информацией, позволяющей вам локализовать причину ошибки. Я приведу общий анализ.

Функция __DBSETLOC располагается в объектном модуле DBCMD5. Если посмотреть ее исходный код, то единственное, что она делает, это устанавливает кодовый блок bFor для активной базы данных, если этот кодовый блок был передан в качестве параметра, и возвращает текущее значение блока bFor. bFor - это кодовый блок, который формируется, когда вы, например, вызываете команду LOCATE, указав в ней опцию FOR. Тогда команда LOCATE, которая реализована с помощью Clipper функции __dblocate, то есть prg модуля, вызывает __DBSETLOC и передает ей этот кодовый блок bFor, который соответствует опции команды LOCATE FOR.

Что может вызвать аварийное завершение функции __DBSETLOC? Единственное - это вызов из этой функции другой внутренней функции Clipper __GetGrip из объектного модуля STACK. Что делает эта функция? Она пытается зафиксировать указатель на кодовый блок в стеке Clipper. Эти фиксированные указатели обрабатываются следующим образом. Если Clipper первый раз пытается фиксировать указатель, то из стека Clipper выделяется некоторый объем памяти для этих указателей. Когда этот объем исчерпывается, то Clipper снова выделяет дополнительную память из стека Clipper. Когда потребность в фиксированном указателе нет, то Clipper вызывает внутреннюю функцию __DropGrip. Но память при этом не возвращается стеку! Просто освобожденные указатели объединяются в односвязный список и помечаются как удаленные. Когда Clipper нужнофиксировать какой-то указатель, то он первым делом просматривает этот список освобожденных указателей.

Не только функция __DBSETLOC выполняет фиксацию указателей на данные в стеке с помощью __GetGrip, но и другие функции, например, при работе со строками, или массивами выполняют подобную операцию.

Итак, подытожим. Ошибка возникла в __DBSETLOC при вызове функции __GetGrip, которая в свою очередь не нашла места в стеке, чтобы зафиксировать указатель на кодовый блок bFor. В этом случае вызывается функция __efault, которая пытается каким-то образом получить память, и если ей не удается, то среди прочих сообщений об ошибке, она выдает сообщение с номером 667, которое вы и получили.

Какой вывод можно сделать из моего анализа? Причиной ошибки является не сама функция __DBSETLOC, а предыдущий ваш код. аварийное завершение __DBSETLOC - это лишь следствие переполнения стека другими операциями вашей программы.

То есть сообщенная вами информация не позволяет сделать заключение, какое место в коде вашей программы стало причиной ошибки. Я лишь могу предположить, что у вас очень много одновременно используется строк, массивов и т.д. Кроме того, если вы используете одновременно все 255 баз данных и для каждой из них выполняете LOCATE, то все 255 баз данных будут хранить кодовый блок bFor. Этот ткодовый блок в любой случае создается командой LOCATE, даже если вы сами не указываете опцию команды FOR. То есть по умолчанию эта команда его кладет равным следующему кодовому блоку

IF ( ISNIL( bFor ) ) 
bFor := { || .T. }
ENDIF


Я конечно понимаю, что вам не стало легче от сообщенной мной информации, но тем не менее вы по крайней мере можете считать, что причина ошибки не в самой __DBSETLOC, а в другом месте вашей программы.

Спасибо: 0 
ПрофильЦитата Ответить



Пост N: 24
Зарегистрирован: 11.10.11
ссылка на сообщение  Отправлено: 14.11.11 17:12. Заголовок: Я хотел бы еще добав..


Я хотел бы еще добавить, что возможно при закрытии базы данных операция закрытия забывает освободить указатель на bFor. Отсюда при частом использовании команды LOCATE может происходить переполнение стека. Это хорошо бы было проверить. Проверку сделать очень просто. Нужно в цикле, допустим, из 100 итераций выполнить следующее: 1) вывести значения внутренних переменных Clipper __estat и __estatlow ; 2) открыть базу данных; 3) вызвать __DBSETLOC, передав ей какой-нибудь кодовый блок 4) закрыть базу данных.

Если при выполнении этого цикла значение __estat будет изменяться и приближаться к значению __estatlow, то значит, что при закрытии bFor не освобождается.

Спасибо: 0 
ПрофильЦитата Ответить
Ответ:
1 2 3 4 5 6 7 8 9
большой шрифт малый шрифт надстрочный подстрочный заголовок большой заголовок видео с youtube.com картинка из интернета картинка с компьютера ссылка файл с компьютера русская клавиатура транслитератор  цитата  кавычки моноширинный шрифт моноширинный шрифт горизонтальная линия отступ точка LI бегущая строка оффтопик свернутый текст

показывать это сообщение только модераторам
не делать ссылки активными
Имя, пароль:      зарегистрироваться    
Тему читают:
- участник сейчас на форуме
- участник вне форума
Все даты в формате GMT  3 час. Хитов сегодня: 159
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет