Проект project1 вызвал класс исключения external sigsegv в файле include
Скажу, как воспроизвожу проблему на lazarus. У меня есть форма и модуль данных, использующий zeos для установления соединения с локальной базой данных оракула. Проблема возникает, когда я помещаю некоторый код для взаимодействия с db. Вот пример:
Это как раз та строка, которая идет по ошибке. Вот полный код формы:
Вот код модуля данных:
Ошибок больше нет, но DBGrid1 не заполнен.
Это файл lpr моего проекта:
Наиболее вероятная причина появления этой ошибки - если OracleMng или ZQuery1 не были созданы. Измените свой код на if (OracleMng <> Nil) and (OracleMng.Zquery1 <> Nil) then OracleMng.ZQuery1.SQL.Clear . Вы все еще получаете ошибку?
@MartynA Это не выдает ошибку, но DBGrid1 не показывает мне результат запроса. Я использую dbgrid1.refresh; Но теперь для каждого запроса я должен делать это «если»?
Я думаю, вам нужно добавить минимальный воспроизводимый пример к вашему q, включая запрос, который вы ожидаете заполнить DBGrid.
Я добавил 3 строки, которые использую в вопросе. В Delphi я использовал этот код, и он работал (с использованием dbexpress): DataModule1.SQLQuery1.Close; DataModule1.SQLQuery1.SQL.Clear; DataModule1.SQLQuery1.sql.add ('обновить справочный набор topic =: topic where info like: called'); DataModule1.SQLQuery1.ParamByName ('topic'). AsString: = 'LAKO'; // используется для Forza ParamByName DataModule1.SQLQuery1.ParamByName ('called'). AsString: = '% вызывается с локального%'; DataModule1.SQLQuery1.ExecSQL;
Дело в том, что изменение я предложил в своем комментарии, а именно
очевидно, вы перестали получать ошибку SIGSEGV, предполагающую, что ваш DataModule и форма создаются в неправильном порядке, т.е. сначала форма. Проверьте это, перейдя в Project | Просмотреть исходный код в среде IDE. Если вы видите что-то вроде
они расположены в неправильном порядке, поэтому поменяйте местами две строки CreateForm
После этого изменения вам больше не понадобится
Следующее: кажется, вы не понимаете, когда использовать
Open предназначен для случаев, когда используемый вами оператор SQL создает набор результатов, то есть набор записей, которые можно просмотреть в TDBGrid. Самый обычный способ сделать это - использовать инструкцию SELECT, как в
ExecQuery предназначен для использования там, где ваш оператор SQL выполняет некоторую операцию с базой данных, которая не включает ВЫБОР записей. Наиболее распространенные операторы SQL, для которых требуется ExecSQL:
хотя есть и другие, например, операторы, которые выполняют хранимые процедуры на SQL Server (обратите внимание, что некоторые хранимые процедуры возвращают наборы результатов и поэтому нуждаются в них Open , а не ExecSQL).
Обратите внимание, что ExecSQL удалит все записи, которые есть в наборе данных (ZQuery1), поэтому после того, как вам нужно будет снова открыть, используя подходящий оператор SQL
Обратите внимание, что я
Причина этого в том, что гораздо легче увидеть весь оператор SQL в отладчике, S проверив переменную, чем проверяя свойство ZQuery1.SQL.Text, и гораздо проще увидеть любые синтаксические ошибки.
Вам всегда следует Close использовать набор данных, который вы редактировали Open после завершения работы с ним, поскольку он обеспечивает актуальность данных на диске. если последней операцией SQL был ExecSQL, вам не нужно закрывать набор данных.
Если вы установите свойство Text запроса, как я, с помощью ZQuery1.SQL.Text, вам не нужно использовать Clear . В любом случае это всего лишь эквивалент выполнения ZQuery1.SQL.Text := '' и не влияет на состояние набора данных - он делает что-либо только тогда, когда вы вызываете ExecSQL или Open .
Привет! Работаю над приложением для работы с оценками учеников. Решил начать с раздела настроек. При вводе кол-ва оценок учащихся проект вызывает класс исключения External:SIGS EGV. Данные вводятся в Edit, после этого они записываются в метод markscount объекта класса TSettinngs. Объект settings и сам класс TSettings находятся в модуле Unit1. Ошибка возникает на 54-ой строке второго модуля.
Unit1:
И ещё: как правильно вызвать процедуру OnClick(в другой процедуре)? Писал так:'Form1.Button1Click ' - компилятор говорит о недостаточном кол-ве параметров, а так:'Form1.Button1Click(Sender:TObject)' - тоже ошибка.
Проект вызвал класс исключения External: SIGSEGV
Здравствуйте. Помогите чем сможете. Компилятор выдает ошибку на 77 строчку не могу понять причину .
Проект вызвал класс исключения External SIGSEGV
Доброго времени суток, пишу программу для работы с классом класс круговое кольцо свойства.
Проект вызвал класс исключения 'External:SIGSEGV'
Здравствуйте! Не могу понять, почему вызывается класс External. Вроде программа для работы метода.
Проект project1 вызвал класс исключения 'External: SIGSEGV'
В файле 'tacustomseries.pas' на строке 809 без строки Chart1.ClearSeries ошибки не возникает. как.
Объект settings должен быть создан перед тем, как к нему обратиться. У тебя в коде я не вижу его создания. Что-то типа:
UI, вот не надо такое советовать. Чтобы правильно пройти все этапы VCL вызывать надо не процедуру, а кнопку. FormX.ButtonY.Click. Или как минимум указывать что было нажато, не всегда будет одна процедура - одна кнопка к тому же.
Чтобы правильно пройти все этапы VCL, надо писать на Дельфи, для начала. Тут LCL. Ну и потом, мне тоже советовать ничего не надо. Я как-нибудь сам разберусь, что кому говорить, а что - нет.
Комментарий я тоже написал не просто потому что было нечего делать. Думающий - поймёт. Не думающему ничего не поможет.
UI, разницы ноль, я просто о том, что ты неправ, это индусский метод - вызывать что-то напрямую пропуская "неважные" этапы, особенно для новичка, и даже к среде отношения не имеет.
Расскажу, как воспроизвожу проблему на lazarus. У меня есть форма и модуль данных, использующий zeos для установления соединения с локальной базой данных оракула. Проблема возникает, когда я помещаю некоторый код для взаимодействия с db. Вот пример:
Это как раз та строка, которая идет по ошибке. Вот полный код формы:
Вот код модуля данных:
Ошибок больше нет, но DBGrid1 не заполнен.
Это файл lpr моего проекта:
Наиболее вероятная причина появления этой ошибки - если OracleMng или ZQuery1 не были созданы. Измените свой код на if (OracleMng <> Nil) and (OracleMng.Zquery1 <> Nil) then OracleMng.ZQuery1.SQL.Clear . Вы все еще получаете ошибку?
Это не выдает ошибки, но DBGrid1 не показывает мне результат запроса. Я использую dbgrid1.refresh; Но теперь для каждого запроса я должен делать это «если»?
Я думаю, вам нужно добавить минимальный воспроизводимый пример к вашему q, включая запрос, который вы ожидаете заполнить DBGrid.
Я добавил 3 строки, которые использую в вопросе. В Delphi я использовал этот код, и он работал (используя dbexpress): DataModule1.SQLQuery1.Close; DataModule1.SQLQuery1.SQL.Clear; DataModule1.SQLQuery1.sql.add ('обновить справочный набор topic =: topic, где информация вроде: называется'); DataModule1.SQLQuery1.ParamByName ('topic'). AsString: = 'LAKO'; // используется для Forza ParamByName DataModule1.SQLQuery1.ParamByName ('called'). AsString: = '% вызывается с локального%'; DataModule1.SQLQuery1.ExecSQL;
1 ответ
Дело в том, что изменение я предложил в своем комментарии, а именно
Очевидно, вы перестали получать ошибку SIGSEGV, предполагающую, что ваш DataModule и форма создаются в неправильном порядке, то есть сначала форма. Проверьте это, перейдя в Project | Просмотреть исходный код в среде IDE. Если вы видите что-то вроде
Они расположены в неправильном порядке, поэтому поменяйте местами две строки CreateForm
После этого изменения вам больше не понадобится
Следующее: кажется, вы не понимаете, когда использовать
Open предназначен для случаев, когда используемый вами оператор SQL создает набор результатов, то есть набор записей, которые можно просмотреть в TDBGrid. Самый обычный способ сделать это заключается в использовании оператора SELECT, как в
ExecQuery предназначен для использования, когда ваш оператор SQL выполняет некоторые операции с базой данных. который не включает ВЫБОР записей. Наиболее распространенные операторы SQL, для которых требуется ExecSQL:
Хотя есть и другие, например, операторы, которые выполняют хранимые процедуры на SQL Server. (обратите внимание, что некоторые хранимые процедуры возвращают наборы результатов и поэтому нуждаются в Open , а не в ExecSQL).
Обратите внимание, что ExecSQL удалит все записи, которые есть в наборе данных (ZQuery1), поэтому после того, как вам нужно будет снова открыть, используя подходящий оператор SQL
Обратите внимание, что я
Причина этого в том, что в отладчике гораздо легче увидеть весь оператор SQL, проверка переменной S , чем проверка свойства ZQuery1.SQL.Text, и намного проще увидеть любые синтаксические ошибки.
Вам всегда следует Close набор данных, который вы Open редактировали после завершения работы с ним, поскольку он обеспечивает актуальность данных на диске. если последней операцией SQL был ExecSQL, вам не нужно закрывать набор данных.
Если вы установите свойство Text запроса, как я, с помощью ZQuery1.SQL.Text, вам не нужно использовать Clear . В любом случае это только эквивалентно выполнению ZQuery1.SQL.Text := '' и не влияет на состояние набора данных - оно делает что-либо только тогда, когда вы вызываете ExecSQL или Open .
Тема изъезжена и уже не мало копий было сломано из-за неё. Так или иначе люди продолжают задаваться вопросом о том может ли приложение написанное на C/C++ не упасть после разыменования нулевого указателя, например. Краткий ответ — да, даже на Хабре есть статьи на сей счёт.
Итак попробуем создать нечто позволяющее решать проблему обработки SIGSEGV-подобных ошибок. Решение должно быть по максимуму кроссплатформенным, работать на всех наиболее распространённых десктопных и мобильных платформах в однопоточных и многопоточных окружениях. Так же сделаем возможным существование вложенных try / catch секций. Обрабатывать будем следующие виды исключительных ситуаций: доступ к памяти по неправильным адресам, выполнение невалидных инструкций и деление на ноль. Апофеозом будет то, что произошедшие аппаратные исключения будут превращаться в обычные C++ исключения.
Наиболее часто для решения аналогичным поставленной задачам рекомендуется использовать POSIX сигналы на не Windows системах, а на Windows Structured Exception Handling (SEH). Поступим примерно следующим образом, но вместо SEH будем использовать Vectored Exception Handling (VEH), которые очень часто обделены вниманием. Вообще, со слов Microsoft, VEH является расширением SEH, т.е. чем-то более функциональным и современным. VEH чем-то схож c POSIX сигналами, для того чтобы начать ловить какие либо события обработчик надо зарегистрировать. Однако в отличии от сигналов для VEH можно регистрировать несколько обработчиков, которые будут вызываться по очереди до тех пор пока один из них не обработает возникшее событие.
В довесок к обработчикам сигналов возьмём на вооружение пару setjmp / longjmp , которые позволят нам возвращаться туда куда нам хочется после возникновения аварийной ситуации и каким-либо способом обрабатывать эту самую исключительную ситуацию. Так же, чтобы наша поделка работала в многопоточных средах нам понадобится старый добрый thread local storage (TLS), который также доступен во всех интересующих нас средах.
Самое простое, что необходимо сделать чтобы просто не упасть в случае аварийной ситуации — это написать свой обработчик и зарегистрировать его. В большинстве случаев людям достаточно просто собрать необходимое количество информации и красиво свернуть приложение. Так или иначе обработчик сигналов регистрируется всем известным способом. Для POSIX-совместимых систем это выглядит следующим образом:
Для Windows код намного короче:
Обработчик один, он ловит сразу все события (не только аппаратные исключения надо сказать) и нет никакой возможности что-либо сделать со стеком как в Linux, например. Единица, подаваемая первым аргументом в функцию AddVectoredExceptionHandler , говорит о том, что наш обработчик должен вызываться первым, перед любыми другими уже имеющимися. Это даёт нам шанс быть первыми и предпринять необходимые нам действия.
Сам обработчик для POSIX систем выглядит следующим образом:
Обработчик для Windows выглядит следующим образом:
Как уже упоминалось выше VEH обработчик на Windows ловит много чего ещё помимо аппаратных исключений. Например при вызове OutputDebugString возникает исключение с кодом DBG_PRINTEXCEPTION_C . Подобные события мы обрабатывать не будем и просто вернём EXCEPTION_CONTINUE_SEARCH , что приведёт к тому что ОС пойдёт искать следующий обработчик, который обработает данное событие. Также мы не хотим обрабатывать C++ исключения, которым соответствует магический код 0xE06D7363L не имеющий нормального имени.
Как на POSIX-совместимых системах так и на Windows в конце обработчика вызывается longjmp , который позволяет нам вернуться вверх по стеку, до самого начала секции try и обойти её попав в ветку catch , в которой можно будет сделать все необходимые для восстановления работы действия и продолжить работу так как будто ничего страшного не произошло.
Для того, чтобы обычный C++ try начал ловить не свойственные ему исключительные ситуации необходимо в самое начало поместить небольшой макрос HW_TO_SW_CONVERTER :
Выглядит довольно кудряво, но по факту здесь делается очень простая вещь:
- Вызывается setjmp , который позволяет нам запомнить место где мы начали и куда нам надо вернуться в случае аварии.
- Если по пути выполнения случилось аппаратное исключение, то setjmp вернёт не нулевое значение, после того как где-то по пути был вызван longjmp . Это приведёт к тому, что будет брошено C++ исключение типа HwException, которое будет содержать информацию о том какого вида ошибка случилась. Брошенное исключение без проблем ловится стандартным catch .
Упрощённо приведённый выше макрос разворачивается в следующий псевдокод:
У подхода setjmp / longjmp есть один существенный недостаток. В случае обычных C++ исключений, происходит размотка стека при которой вызываются деструкторы всех созданных по пути объектов. В случае же с longjmp мы сразу прыгаем в исходную позицию, никакой размотки стека не происходит. Это накладывает соответствующие ограничения на код, который находится внутри таких секций try , там нельзя выделять какие-либо ресурсы ибо есть риск их навсегда потерять, что приведёт к утечкам.
Ещё одним ограничением является то, что setjmp нельзя использовать в функциях/методах объявленных как inline . Это ограничение самого setjmp . В лучшем случае компилятор просто откажется собирать подобный код, в худшем он его соберёт, но полученный бинарный файл будет просто аварийно завершать свою работу.
Для того, чтобы решение работало в многопоточных окружениях необходимо чтобы каждый поток имел собственное место где можно сохранять контекст исполнения с помощью setjmp . Для этих целей и используется TLS, в использовании которого нет ничего хитрого.
Сам контекст исполнения оформлен в виде простого класса имеющего следующие конструктор и деструктор:
Данный класс имеет поле prev_context , которое даёт нам возможность создавать цепочки из вложенных секций try / catch .
В доказательство того, что всё работает как описано имеется автоматическая сборка и тесты под платформы Windows, Linux, Mac OS X и Android:
Под iOS это тоже работает, но за неимением устройства для тестирования нет и автоматических тестов.
В заключение скажем, что подобный подход можно использовать и в обычном C. Надо лишь написать несколько макросов, которые будут имитировать работу try / catch из C++.
Так же стоит сказать, что использование описанных методов в большинстве случаев является очень плохой идеей, особенно, если учесть, что на уровне сигналов нельзя выяснить, что же привело к возникновению SIGSEGV или SIGBUS . Это равновероятно может быть как и чтение по неправильным адресам так и запись. Если же чтение по произвольным адресам является операцией не деструктивной, то запись может приводить к плачевным результатам таким как разрушением стека, кучи или даже самого кода.
Хотел как честный человек работать на бесплатном софте поставил lazarus c fpc и отладчиком migw, беру простейший пример по инициализации окна в opengl, проект собирается нормально, но стоит его запустить из под IDE как вылазиет эта наглая ошибка, хотя если просто запустить exe то проблем нету, обшарил все форумы пишут что виноват comodo и описывают как добавить его в исключения, но comodo у меня никогда не стоял, стоит только касперский но я пробовал его отключать ничего не помогает, качал последнюю версию migw такая же ситуация. В чем тут косяк может быть уже второй день пошел как я трачу нервы.
лазарус очень глючная среда, иногда не копилила код, до перезапуска среды, периодически отрудается суфлер кода, и про размер получаемых экзешников лучше промолчать. Зачем ты хоть ее выбрал.
Ситуация такая проект задумывается такой: серверную часть игры написать под линукс, а саму игру для пользователя делать под виндовс, поэтому подумал писать на нем чтоб боле мене код сделать кросплатформенным, а тут такие косяки уже при простейшем коде, что я уже боюсь дальше что-либо кодить на нем ((
Kavis
> серверную часть игры написать под линукс, а саму игру для пользователя делать
> под виндовс, поэтому подумал писать на нем чтоб боле мене код сделать
> кросплатформенным, а тут такие косяки уже при простейшем коде, что я уже боюсь
> дальше что-либо кодить на нем ((
Может, легче написать все в дельфи, а когда все будет готово портировать на лазарус?
Отладчик mingw (точнее gdb) все равно слабо пригоден для fpc, свойства смотреть не умеет, с потоками не работает и т.д. Так что отлаживай через лог.
MAMONT-92
> про размер получаемых экзешников лучше промолчать
1-2 Мегабайта, сопоставимо с дельфи. А 10+Мб получается если компилировать с отладочной информацией.
Видимо другой отладчик нужно заюзать :).
kipar
А кроме Мингэвешного отладчика есть какие-нить ещё?
А то тоже иногда бывает страдаю такой проблемой)
ExeLord
Паскалевского нету, во всяком случае я не встречал. Там в папке lazarus\debugger\fpdebug\fpd есть заготовка для него, но разработчикам видимо не до того.
А любой сишный будет еще хуже gdb, т.к. вообще не имеет представления о синтаксисе паскаля.
kipar
> А любой сишный будет еще хуже gdb, т.к. вообще не имеет представления о
> синтаксисе паскаля.
Ну это ясно.
Ладно, жду с нетерпением отладчик от разрабов)
А так, и без него прожить можно. Пока и гбд не сильно парит.
Кстати, в случае постоянного SIGSEGV, вследствии магнитных бурь на солнце, квантовой флуктуации и прочей нечести
можно ли отключить отладчик и заставить Лазарь запускать ехе вчистую (просто лень папку открывать и руками делать :) )?
В общем я подумал все взвесил и пришел к выводу ,что проще заплатить за делфи и виндос сервер, чем гемороиться. просто идея была игру писать типа так сервер игры на облачном сервере с ОС линукс, а клиент игры на винде, и чтоб проще было в переносе кросплатформенности делать через FPC но как я посмотрел цены на VDS на облачные почти одинаковы что сервер на винду, что сервер на линукс, в общем проще писать на делфи под винду - хрен с ними с парами штуками дерявянных, но я знаю за что их отдам, чем так страдать ((
kipar
> Отладчик mingw (точнее gdb) все равно слабо пригоден для fpc, свойства смотреть
> не умеет, с потоками не работает и т.д. Так что отлаживай через лог.
Умеет смотреть он свойства, просто галочку оптимизации не нужно ставить на самую высокую -O1.
> 1-2 Мегабайта, сопоставимо с дельфи. А 10+Мб получается если компилировать с
> отладочной информацией.
Там есть галочка, компилировать отладочную информацию в отдельном файле.
Kavis
> В общем я подумал все взвесил и пришел к выводу ,что проще заплатить за делфи и
> виндос сервер, чем гемороиться. просто идея была игру писать типа так сервер
> игры на облачном сервере с ОС линукс, а клиент игры на винде, и чтоб проще было
> в переносе кросплатформенности делать через FPC но как я посмотрел цены на VDS
> на облачные почти одинаковы что сервер на винду, что сервер на линукс, в общем
> проще писать на делфи под винду - хрен с ними с парами штуками дерявянных, но я
> знаю за что их отдам, чем так страдать ((
Выбор FPC или Delphi для сервера самый глупый, для этих целей лучше выбрать Java или по-проще node.js, где для начала хоть есть сборщик мусора и куча готовых решений как под первое, так и под второе.
DevelS
Я же не веб-сервер собрался писать, а сервер для игры.
Ну да я немного попутал, без разницы, сервер.
ExeLord
> можно ли отключить отладчик и заставить Лазарь запускать ехе вчистую (просто
> лень папку открывать и руками делать :)
Да, Сервис\Параметры\Отладчик\выбираем (none).
Ну и компилим без отладочной информации, тогда и процесс компиляции ускоряется (хотя может у меня просто винт тормозной).
DevelS
> Умеет смотреть он свойства, просто галочку оптимизации не нужно ставить на
> самую высокую -O1.
Нет, он поля умеет смотреть. А свойства, скажем TList.Count (а не FCount) у меня даже без оптимизации не показывал. Хотя могли уже пофиксить.
DevelS
> Там есть галочка, компилировать отладочную информацию в отдельном файле.
У меня при этой галочке отладчик никаких символов не видит. Хотя может руки кривые - есть какой-нибудь способ IDE указать чтоб оно получаемый .gdb использовало?
Kavis
SIGSEGV - это же сигнал в UNIX, уведомляющий об ошибке обращения к памяти. Причём тут .exe? В Windows нету таких сигналов.
Кирюшык
Lazarus называет этим словом Access Violation.
kipar
> У меня при этой галочке отладчик никаких символов не видит. Хотя может руки
> кривые - есть какой-нибудь способ IDE указать чтоб оно получаемый .gdb
> использовало?
У меня отладка работала стабильно при отдельном файле, по крайней мере в винде.
Читайте также: