Range check error c builder

Components for Delphi and C++ Builder. Текущее время: 15 янв 2023, 22:00 Часовой пояс: UTC Ошибка Range check error Страница 1 из 1 [ Сообщений: 3 ] Для печати Предыдущая тема | Следующая тема Автор Сообщение Kverde Зарегистрирован: 28 окт 2013, 05:47Сообщений: 14 При клике на «+» и появлении DetailPanel появляется ошибка Range check […]

Joined: 02 Dec 2012, 23:19
Posts: 15

I know I can fix it in this way, but I think this is not a good practice and OnSelectionChanged event shouldn’t be frequently fired while refreshing selectedRows list. It is only a simplest example which I made to show you a problem. In real app this is much more complicated. Record deleting and other changes are made using code which don’t know anything about UI elements. Additionaly I must to use this solution for every instance of the grid in my apps and this is a lot of tests and work.

If you don’t want to change this in library code so maybe just can give a possibility to set class to for SelectedRows property. It could be done exactly like for grid columns:

This function can be overrided in derived class and other class can be used to support SelectedRows property. In this way I would could to change myself this behavior for my needs.

best regards
Adam Siwon

All times are UTC

Who is online

Users browsing this forum: No registered users and 1 guest

Источник

Блог GunSmoker-а

. when altering one’s mind becomes as easy as programming a computer, what does it mean to be human.

11 мая 2009 г.

Access Violation в деталях

Примечание для людей, заходящих сюда из поисковика: эта статья написана для разработчиков программ. Если вы не программист и не пытаетесь исправить ошибку в СВОЕЙ программе, эта статья — не для вас. До свидания. Извините, что потратил ваше время.

Примечание для студентов/новичков, пишущих на Delphi/C++ Builder: эта статья написана для диагностики исключений в вашей программе. Если вместо этого вы получаете ошибки от самой IDE (а не от вашей программы), например, access violation в пакете dclite60.bpl, то эта статья — не для вас. Чтобы решить проблемы с IDE — идите сюда. Краткий ответ: не надо использовать динозавров (Delphi 5/6/7), используйте современные IDE (Delphi XE и выше). Если всё же хочется динозавров, то часто причиной является DEP. Т.е. нужно добавить Delphi/Builder в исключения DEP. Ну или на крайний случай — отключить/удалить конфликтующий пакет.

Итак, для всех прочих (а именно: разработчиков Delphi/C++ Builder, пытающихся решить проблему возникновения исключения Access Violation в своей программе) — приступим!

Исключение класса EAccessViolation — это самое частое исключение в Delphi-программах. Я хотел бы рассмотреть, что это такое, когда возникает, и как с ним бороться. Этот пост скорее для начинающих, поэтому данные могут излагаться с упрощением.

Примечания:

  • если вы совсем начинающий или студент/студентка и получили Access Violation — первым делом включите опцию Range Check Errors (Project/Options, вкладка Compiler) и сделайте Project/Build.
  • если вы плохо или совсем не понимаете, что такое указатели и/или объекты — рекомендую сначала прочитать эту статью.
  • если вы плохо или совсем не умеете работать с отладчиком IDE (или даже не знаете, что это такое) — прочитайте сначала эту статью.

Что такое Access Violation

Каждая программа использует при работе память (*). Память занимает любая переменная в вашей программе. Будь это форма, компонент, массив, запись, строка или же простой Integer . Под некоторые переменные память выделяется автоматически (например, под переменные типа Integer и статические массивы), под другие — вы должны выделять её сами, явно (например, динамические массивы). Собственно, с точки зрения операционной системы каждая переменная характеризуется адресом в памяти (местоположением) и размером. Понятно, что обычно данные разных переменных не пересекаются — за исключением случаев обращением к одной области памяти через разные имена с помощью указателей.

Грубо говоря, обычно в программе используется три типа памяти: область памяти для глобальных переменных, стек и куча.

Память для глобальных переменных выделяется загрузчиком ОС при загрузке исполняемого модуля программы в память и освобождается при выгрузке модуля (выходе из программы). Глобальные переменные — это любые переменные, объявление которых располагается вне класса или процедуры. Стек используется для размещения локальных переменных (объявленных в процедуре/функции) и служебных данных (типа адресов возврата и адресов обработчиков исключений). Куча же используется для размещения динамических данных.

Заметим, что для переменных динамических типов данных (динамические массивы, строки, любые объекты, компоненты), хотя сама переменная может размещаться в области для глобальных переменных или в стеке (а, значит, память для неё выделяется автоматически), но данные, на которые она указывает, всегда размещаются в куче и, зачастую, должны управляться вручную.

Вне зависимости от того, кто выделяет память для переменной (вы вручную или компилятор автоматически), память для любой переменной должна быть выделена перед использованием, а потом, когда переменная уже не будет нужна — освобождена.

Иногда из-за ошибок в коде программы происходит ситуация, когда программа при выполнении пытается получить доступ к памяти, которая не была выделена или уже была освобождена. Когда такое происходит, процессор возбуждает исключение класса EAccessViolation . Обычный текст ошибки в приложении Delphi — «Access violation at address XXX in module ‘YYY’. Write/read of address ZZZ» («Нарушение доступа по адресу XXX в модуле ‘YYY’. Попытка записи/чтения в ZZZ»). Хотя причина этого исключения всего одна (попытка обращения к недействительной памяти), но эта ошибка может проявлять себя в весьма разном виде и коде.

Более подробно об указателях и памяти говорится в уже упоминавшейся выше статье.

Ищем место возникновения Access Violation

Как, собственно, бороться с этими ошибками? Ну, если вы получили EAccessViolation под отладчиком:


То нужно просто нажать на «Break» («Ok» в старых версиях Delphi) и отладчик сразу же ткнёт вас на строчку с ошибкой. Также можно посмотреть стек вызовов (в меню Delphi — View/Debug windows/Call Stack):


В этом окне будет показано, как же вы туда попали. Читается это дело сверху вниз (текущее место помечено стрелочкой). Можно дважды щёлкать по строкам в этом окне для перехода в код, соответствующий этой строке.

Иными словами, отладчик сразу же тыркает вас в строку с ошибкой.

Если же вы используете средства автоматической диагностики типа EurekaLog/madExcept, то вместо обычного сообщения об ошибке вы получите баг-отчёт, в котором будет виден тот же самый Call Stack (вид стека вызова может отличаться из-за различных методов его получения):


Не имеет значения, столкнулись ли вы с проблемой во время отладки или получили баг-отчёт от EurekaLog для уже распространяемой программы — хорошо бы подготовиться к этой ситуации заранее и включить опции проекта, упрощающие отладку. Как правило, это опции «Use Debug DCUs» и «Stack frames».

Окей, найти место ошибки — это только пол-дела. Определить почему же в этой строке возникла ошибка — это вторые пол-дела.

Ищем причину возникновения Access Violation анализом кода

Если ситуация возникла у вас в отладчике, то тут всё относительно просто: вам нужно установить точку останова на проблемную строчку и проверить значения всех переменных и выражений, участвующих в ней — вот вам и причина ошибки, находится сразу же. Я не буду подробно останавливаться на теме отладки здесь, более подробно об этом написано в моей статье, часть 2 (осторожно: большой размер).

В случае, если у вас на руках есть только баг-репорт, а не ситуация под отладчиком, то вам придётся использовать свои телепатические способности, которые обычно развиваются с опытом. Дабы помочь вам в этом, здесь я как-раз и хочу рассмотреть типичные причины возникновения ошибки Access Violation.

1. Во-первых, это всевозможные ошибки выхода за границы массивов. Например, типичная ошибка новичка может выглядеть так:
Если в вашей проблемной строке есть скобочки типа [], то у вас есть хороший довод к проверке допустимости выражения в [].

Обычно такие ошибки нужно отлавливать на стадии отладки, включая опцию Range Check Errors. Дело в том, что подобные ошибки весьма опасны тем, что могут пройти незамеченными (и потом редко ловятся при эксплуатации программы), даже более того — они могут разрушить стек, так что нельзя будет получить место возникновения ошибки. Но об этом позже.

2. Различного рода неверные передачи параметров. Обычно эти ошибки отлавливаются во время разработки и тестирования, нежели во время эксплуатации программы. Чаще всего они возникают при использовании процедур с нетипизированными параметрами. Сюда же относятся различные варианты ошибок переполнения буфера, например:
Для избавления от таких ошибок нужно просто внимательно изучать документацию на функции: что они ожидают увидеть и что вы действительно им подсовываете.

3. Передачи данных между двумя менеджерами памяти. Обычно ошибки такого плана возникают при передаче данных из DLL в приложение или наоборот. а также между двумя DLL. Чаще всего новички любят передавать из/в DLL строки типа String .

Причины этого я рассматривал ранее. Эти ошибки обычно отлавливаются немедленно во время разработки программы и очень редко доживают до рабочей программы. Решаются эти проблемы правильным проектированием.

4. Неверное объявление функций, импортируемых из DLL. Наиболее часто путают модель вызова. Если у вас получается EAccessViolation при вызове функции из DLL — просто внимательно посмотрите на её объявление и убедитесь, что её сигнатура верна — чаще всего пропускают модель вызова, stdcall или cdecl .

Хотя обычно ошибки такого плана отлавливаются на этапе разработки, тем не менее могут быть ситуации, когда ошибка проползает в готовую программу. Вот увлекательная история Реймонда Чена о том, как программа может работать с неверно объявленным прототипом функции (довольно интересны и посты в серии до и после этого).

5. Отсутствие синхронизации при работе с потоками. Если вы делаете программу с использованием нескольких потоков, то у вас могут быть проблемы, если вы не обеспечили необходимой синхронизации. Например, любые обращения к VCL запрещены из вторичных потоков — вам нужно использовать Synchronize . Собственно, проблемы тут возникают, когда один поток меняет данные с которыми работает второй поток — что для последнего становится полной неожиданностью.

К сожалению, ошибки с синхронизацией потоков наиболее тяжело диагностировать. Лучшее, что вы можете сделать — прогарантировать, что такие проблемы никогда не возникнут: используйте Synchronize и/или заключайте код в критические секции при работе с разделяемыми потоками переменными. Иногда проблемы возникают из-за использования CreateThread вместо BeginThread или TThread (из-за отсутствия установки IsMultiThreaded ).

6. Вызовы функций или процедур по процедурной переменной, когда она содержит неверное значение. Например:
Ситуация очень сильно напоминает следующий пункт и бороться с нею нужно такими же методами.

7. Вызовы методов или любые другие обращения к объектам или компонентам, которые ещё не созданы или же были уже удалены. Подозревать эту причину нужно, когда в проблемной строке у вас участвует переменная-объект или компонент. Особенно, если вы хоть где-то в программе занимаетесь ручным созданием или освобождением компонентов или объектов.

Проблема в том, что при освобождении компонента, его ссылка-переменная не меняется, продолжая указывать на уже удалённую память. Кроме того, локальные переменные не инициализируются автоматически при входе в процедуру и содержат мусор. Вот пример подобного рода ошибок:
Как мы уже говорили ранее, в приложениях Delphi есть служебный код, называемый «менеджером памяти», который отвечает за выделение и освобождение памяти в вашей программе и служит прослойкой между низкоуровневыми функциями операционной системы и вашим кодом. При всей своей пользе менеджер памяти, однако, добавляет в программу одну проблему: из-за него в программе находится куски памяти, которые выделены с точки зрения операционной системы, но свободны с точки зрения программы. Например, удалили вы компонент, но менеджер памяти не отдаёт память системе немедленно, придерживая её для дальнейшего использования.

Поэтому все ошибки доступа к памяти опасны в первую очередь тем, что могут пройти незамеченными. Например, мы обращаемся к уже удалённому объекту, но поскольку менеджер памяти ещё не отдал эту память системе, то обращение может пройти успешно. Чуть ранее мы говорили, что для предотвращения таких ситуаций вам нужно использовать FreeAndNil и другие механизмы. Ситуация ещё хуже с локальными массивами: дело в том, что локальные массивы размещаются в стеке, в котором обычно есть довольно большие участки размещённой памяти по краям массива. Что ещё хуже, эта память обычно реально используется программой (в отличие от памяти, которую мы освободили при удалении объекта), так что вы можете, спокойно промахнувшись, записать что-то не туда, и в итоге, ошибка всплывёт в совершенно другом месте из-за испорченных данных. Чтобы сделать ситуацию ещё хуже: в стеке хранятся и служебные данные программы, необходимые для её выполнения — это адреса возврата и обработчики исключений.

Например:
Весьма коварные ситуации, не правда ли? В зависимости от того, как именно мы ошибёмся в индексе массива, мы можем получить (**):
а). Программу, выдающую правильные результаты.
б). Программу, выдающую неверные результаты.
в). Программу, возбуждающую исключение.
г). Программу, вылетающую вообще.
Причём одна и та же программа с таким багом может показывать любое из этих поведений, смотря по тому, на какой машине она запущена и в каких условиях/окружении выполняется.

Вот почему чрезвычайно важно использовать опцию Range Check Errors во время разработки и тестирования.
Ну, вы можете также включить её и для release-версии кода, если не уверены в качестве своей стадии тестирования.

Итак, что, собственно, нужно сделать, когда мы получили Access Violation? Ну, с помощью предыдущего пункта мы находим строку с ошибкой, а дальше пытаемся по пунктам подставить возможные причины:
— Есть в строке []? — подумаем, а не может ли у нас быть неверный индекс?
— Есть работа с объектами? Проследим, какова логика работы — не удаляется ли объект раньше времени?
— Используем DLL? А правильно ли объявлена функция? А уж не обмениваемся ли мы динамическими данными (строками, там, массивами)?
и т.д.

Существенную помощь в таком анализе нам поможет следующий пункт.

Ищем причину возникновения Access Violation анализом данных

Во-первых, мы можем попытаться вытащить информацию из самого сообщения об ошибке. Напомним его вид:

Access violation at address XXX in module ‘YYY’. Write/read of address ZZZ.

Во-первых, адрес XXX указывает на точное место в программе, где произошла ошибка. Именно по этому адресу отладчик Delphi и EurekaLog ищут строчку для показа её вам. Также модуль, которому она принадлежит, показывается в сообщении как YYY. Обычно это ваша программа, DLL или системная DLL. Однако, иногда это может быть и совершенно левое значение. Например, если в сообщении не указан модуль или значение XXX выглядит подозрительно (меньше $400000 или больше $7FFFFFFF ), то у вас либо проблемы с перезаписью стека (пункт «в» в конце предыдущего раздела), либо вызов неверной функции (пункт 6 или, иногда, 4 из предыдущего раздела).

Следующий полезный кусок информации — это слово «write» или «read». Первое означает, что возникла проблема при записи информации, второе — что проблема была при чтении. Соответственно, вам нужно проверять в строке кода либо операции записи, либо операции чтения. Например, если проблемная строка была » P := W; «, то вам нужно обратить внимание на P , если в сообщении стоит «write». Если же там стоит «read», то нужно проверять, что же у нас с W .

И последний кусок информации, который можно извлечь из сообщения — это ZZZ. Собственно, точное значение нас обычно не волнует. Важен только факт — велико оно или мало. Мало — это что-то типа $00000000, $0000000A, $00000010 и т.п. Большие значения — это, например, $00563F6A, $705D7800 и др. Если ZZZ мало, то у вас идёт обращение по ссылке равной nil . Если оно велико, то у вас идёт обращение по ненулевой, но мусорной ссылке. В первом случае вам нужно искать, зачем же вы полезли по ссылке равной nil (или кто же освободил переменную раньше времени), во втором случае вам нужно понять, кто же это такой освободил объект, а ссылку не занулил. Короче говоря, это значение (так же, как и с «write»/»read») помогает сузить область поиска.

Помимо сообщения, если у вас есть баг-репорт, вы можете проанализировать значения регистров и состояние памяти. В этом вам помогут две последние вкладки в отчёте EurekaLog:



На первой вкладке вы можете видеть ассемблерный листинг своей программы. Приводится он здесь только для удобства — чтобы не надо было лезть ещё куда-то, чтобы подсмотреть его. Никакой информации он не несёт. А вот на второй вкладке вы можете видеть состояние регистров, (части) стека и (части) памяти в момент исключения. В данном случае мы смотрим на ассемблерный листинг и видим, что в проблемной команде участвуют регистры eax и edx . По вкладке CPU мы находим, что eax равен 0 , что означает, что мы пытаемся присвоить значение по указателю, равному nil . Взглянув на строчку исходника, которую мы узнали из стека вызовов, мы узнаем имя переменной. Вот вам и причина: переменная оказалась равна nil .

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

В следующий раз мы поговорим о ситуациях, когда у вас в коде есть ошибка, но никакого исключения не возбуждается. Частично мы уже говорили об этом здесь (например, пункт «1» и пункты «а»-«б» в конце второго раздела). Но в следующий раз мы пойдём чуть дальше и посмотрим, что ещё можно сделать для отлова таких ситуаций. И, в любом случае, у вас всегда есть возможность переписать код 😉

Источник

Adblock
detector

    msm.ru

    Нравится ресурс?

    Помоги проекту!

    [!] Как относитесь к модерированию на этом форуме? Выскажите свое мнение здесь

    >
    Range Check error
    , Range Check error

    • Подписаться на тему
    • Сообщить другу
    • Скачать/распечатать тему



    Сообщ.
    #1

    ,
    13.06.11, 16:19

      Member

      **

      Рейтинг (т): нет

      Пишу программу которая будет из строки брать нужные символы и ставить как мне надо их..

      ExpandedWrap disabled

        void __fastcall TForm1::Button2Click(TObject *Sender) {

            AnsiString res, res1, ress;

            String c;

            int len = RichEdit1->Lines->Count;

            int i = 0;

            while (i != len) {

                c = RichEdit1->Lines->Strings[i];

                if (RichEdit1->Lines->Strings[i] != «Birthday») {

                    res += c[9];

                    res += c[10];

                    res += c[6];

                    res += c[7];

                    res += c[3];

                    res += c[4];

                    res += «rn»;

                }

                else {

                    res += «-«;

                    res += «rn»;

                }

                i++;

            }

            Memo2->Lines->Add(res);

            Memo2->Lines->SaveToFile(«res.txt»);

        }

      Но пишет Range Check error, я уже по разному пробивал , кто то сталкивался с таким?? Хелп

      П.С. Текст загружаю в очень RichEdit большой метров 30!!
      формата:
      1967-06-06
      1967-06-21
      1968-06-04


      trainer



      Сообщ.
      #2

      ,
      13.06.11, 17:01

        Очевидно, вылезаешь за границы массива.

        Цитата xaduw @ 13.06.11, 16:19

        я уже по разному пробивал

        Попробуй отладчик. Понравится.

        P.S. А в чем смысл использования здесь цикла while?


        xaduw



        Сообщ.
        #3

        ,
        13.06.11, 17:03

          Member

          **

          Рейтинг (т): нет

          Да и For пробивал… и не получается…


          Adil



          Сообщ.
          #4

          ,
          13.06.11, 17:57

            Откуда уверенность, что c[что-то там] не выходит за длину строки? Учитываешь, кстати, что для VCL-ных строк индексация начинается с 1?


            xaduw



            Сообщ.
            #5

            ,
            13.06.11, 18:24

              Member

              **

              Рейтинг (т): нет

              Да пробивал и с 1 .. никак..


              artsb



              Сообщ.
              #6

              ,
              13.06.11, 18:37

                Откуда уверенность на счёт этих индексов:

                ExpandedWrap disabled

                              res += c[9];

                              res += c[10];

                              res += c[6];

                              res += c[7];

                              res += c[3];

                              res += c[4];

                Пробуй так:

                ExpandedWrap disabled

                              res += c[8];

                              res += c[9];

                              res += c[5];

                              res += c[6];

                              res += c[2];

                              res += c[3];

                Сообщение отредактировано: artsb — 13.06.11, 18:41


                xaduw



                Сообщ.
                #7

                ,
                13.06.11, 19:32

                  Member

                  **

                  Рейтинг (т): нет

                  индексы в норме:((


                  artsb



                  Сообщ.
                  #8

                  ,
                  13.06.11, 19:39

                    Цитата xaduw @ 13.06.11, 19:32

                    индексы в норме

                    Судя по ошибке — нет.
                    Или же эта ошибка возникает на другом участке кода, который вы не привели.


                    xaduw



                    Сообщ.
                    #9

                    ,
                    13.06.11, 19:42

                      Member

                      **

                      Рейтинг (т): нет

                      я бросил весь код который есть, я менял индексы как вы говорили , не помогает!!!


                      artsb



                      Сообщ.
                      #10

                      ,
                      13.06.11, 20:00

                        Не попадаются ли даты такого вида:
                        1967-6-21


                        xaduw



                        Сообщ.
                        #11

                        ,
                        13.06.11, 20:10

                          Member

                          **

                          Рейтинг (т): нет

                          нет я уже это проверял:(


                          artsb



                          Сообщ.
                          #12

                          ,
                          13.06.11, 21:33

                            Замечал, что иногда компоненты TMemo и TRichEdit добавляют пустую строку в конец. А пустая строка не равна «Birthday» и, следовательно, удовлетворяет условию:

                            ExpandedWrap disabled

                              if (RichEdit1->Lines->Strings[i] != «Birthday») {

                            При обращении по индексу, происходит AV.

                            Пробуйте так:

                            ExpandedWrap disabled

                                  void __fastcall TForm1::Button2Click(TObject *Sender) {

                                      AnsiString res, res1, ress;

                                      String c;

                                      int len = RichEdit1->Lines->Count;

                                      int i = 0;

                                      while (i != len) {

                                          c = RichEdit1->Lines->Strings[i];

                                          if (c.IsEmpty()) {

                                              i++;

                                              continue;

                                          }

                                          if (c != «Birthday») {

                                              res += c[9];

                                              res += c[10];

                                              res += c[6];

                                              res += c[7];

                                              res += c[3];

                                              res += c[4];

                                              res += «rn»;

                                          }

                                          else {

                                              res += «-«;

                                              res += «rn»;

                                          }

                                          i++;

                                      }

                                      Memo2->Lines->Add(res);

                                      Memo2->Lines->SaveToFile(«res.txt»);

                                  }


                            Dem_max



                            Сообщ.
                            #13

                            ,
                            14.06.11, 04:23

                              я бы сделал так
                              if(c.AnsiPos(«Birthday»);


                              leo



                              Сообщ.
                              #14

                              ,
                              14.06.11, 06:13

                                Поскольку код расчитан на разбор строк из 10-и символов, то соотв-но и нужно юзать условие

                                ExpandedWrap disabled

                                  if (c.Length() == 10) {…}

                                тогда и отдельные проверки на IsEmpty и !=»Birthday» не нужны


                                #SI#



                                Сообщ.
                                #15

                                ,
                                14.06.11, 10:47

                                  Цитата leo @ 14.06.11, 06:13

                                  Поскольку код расчитан на разбор строк из 10-и символов

                                  Не факт, нет гарантии, что нет концевых пробелов.

                                  ExpandedWrap disabled

                                    void __fastcall TForm1::Button5Click(TObject *Sender) {

                                      Memo2->Lines->Clear();

                                      for (int i = 0; i < Memo1->Lines->Count; i++) {

                                        String c = Memo1->Lines->Strings[i];

                                        String res = «»;

                                        if (c.Length() >= 10) {

                                          res += c[9];

                                          res += c[10];

                                          res += c[6];

                                          res += c[7];

                                          res += c[3];

                                          res += c[4];

                                        }

                                        else res += «-«;

                                        Memo2->Lines->Add(res);  // зачем наколачивать в неё ВСЁ, когда можно хранить промежуточные  результаты!

                                      }

                                      Memo2->Lines->SaveToFile(«res.txt»);

                                    }

                                  Сообщение отредактировано: #SI# — 14.06.11, 10:49

                                  0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)

                                  0 пользователей:

                                  • Предыдущая тема
                                  • Borland C++ Builder/Turbo C++ Explorer
                                  • Следующая тема

                                  Рейтинг@Mail.ru

                                  [ Script execution time: 0,0514 ]   [ 16 queries used ]   [ Generated: 10.02.23, 01:27 GMT ]  

                                  На чтение 3 мин Обновлено 16.01.2023

                                  Components for Delphi and C++ Builder.

                                  Текущее время: 10 янв 2023, 11:42

                                  Часовой пояс: UTC

                                  Ошибка Range check error

                                  Страница 1 из 1 [ Сообщений: 3 ]
                                  Для печати Предыдущая тема | Следующая тема
                                  Автор Сообщение
                                  Kverde

                                  Зарегистрирован: 28 окт 2013, 05:47
                                  Сообщений: 14

                                  При клике на «+» и появлении DetailPanel появляется ошибка Range check error

                                  Ошибка нас строке

                                  На отдельном приложении повторить не удалось.
                                  Delphi 2010, EhLib 7.0.143

                                  EhLibSupport

                                  Зарегистрирован: 21 дек 2011, 18:48
                                  Сообщений: 1473

                                  Постарайтесь определить больше условий при которых возникает ошибка.
                                  Чтобы ее исправить, нам надо воспроизвести ее у себя.

                                  Dm_Ufa

                                  Зарегистрирован: 19 мар 2013, 04:23
                                  Сообщений: 12

                                  Ошибка возникает при движении мышкой над пустой областью грида (где кончились записи) и FrozenCols > 0.

                                  Еще возникала также при движении на пустой области, когда нет заголовка у грида, лечил установкой VTitleMargin=-20;

                                  Страница 1 из 1 [ Сообщений: 3 ]

                                  Часовой пояс: UTC

                                  Кто сейчас на форуме

                                  Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2

                                  Источник

                                  Components for Delphi and C++ Builder.

                                  It is currently 10 Jan 2023, 11:42

                                  All times are UTC

                                  DbGridEh Range check error

                                  Page 1 of 1 [ 3 posts ]
                                  Print view Previous topic | Next topic
                                  Author Message
                                  ASiwon

                                  Joined: 02 Dec 2012, 23:19
                                  Posts: 15

                                  today I found in my app Range check error exception. It is raised in incorporation with DbGridEh — I think this is probably bug in DbGridEh. I have the following code:

                                  procedure TForm1.FormCreate(Sender: TObject);
                                  var
                                  i: Integer;
                                  begin
                                  for i := 1 to 10 do
                                  begin
                                  ADMemTable1.Append;
                                  ADMemTable1.FieldByName(‘Id’).AsInteger := i;
                                  ADMemTable1.Post;
                                  if i > 7 then
                                  dbgrdh1.SelectedRows.CurrentRowSelected := True;
                                  end;
                                  end;

                                  procedure TForm1.btn1Click(Sender: TObject);
                                  var
                                  i: Integer;
                                  begin
                                  with ADMemTable1 do
                                  begin
                                  ADMemTable1.DisableControls;
                                  try
                                  for i := dbgrdh1.SelectedRows.Count — 1 downto 0 do
                                  begin
                                  GotoBookmark(dbgrdh1.SelectedRows[i]);
                                  Delete;
                                  end;
                                  finally
                                  ADMemTable1.EnableControls; // Attachments:

                                  EhLib RangeExceed error.zip [87.09 KiB]
                                  Downloaded 131 times
                                  Top
                                  Administrator
                                  Администратор

                                  Joined: 22 Dec 2011, 20:19
                                  Posts: 335

                                  You can fix your btn1Click event without using BeginUpdate/EndUpdate
                                  Have a look —

                                  ASiwon

                                  Joined: 02 Dec 2012, 23:19
                                  Posts: 15

                                  I know I can fix it in this way, but I think this is not a good practice and OnSelectionChanged event shouldn’t be frequently fired while refreshing selectedRows list. It is only a simplest example which I made to show you a problem. In real app this is much more complicated. Record deleting and other changes are made using code which don’t know anything about UI elements. Additionaly I must to use this solution for every instance of the grid in my apps and this is a lot of tests and work.

                                  If you don’t want to change this in library code so maybe just can give a possibility to set class to for SelectedRows property. It could be done exactly like for grid columns:

                                  This function can be overrided in derived class and other class can be used to support SelectedRows property. In this way I would could to change myself this behavior for my needs.

                                  best regards
                                  Adam Siwon

                                  Page 1 of 1 [ 3 posts ]

                                  All times are UTC

                                  Who is online

                                  Users browsing this forum: No registered users and 2 guests

                                  Источник

                                  Читайте также:  Load library failed with error 87 параметр задан неверно viber

                                  Adblock
                                  detector

                                  ошибка

                                  Что обозначает ошибка Range Check Error при использовании NMHTTP???

                                  8 ответов

                                  1

                                  11 ноября 2005 года

                                  kot_

                                  7.3K / / 20.01.2000

                                  Цитата:

                                  Originally posted by Zephyr
                                  Что обозначает ошибка Range Check Error при использовании NMHTTP???

                                  Range Check Error генерируется как правило в случае если происходит попытка обращения к элементу массива по несуществующему индексу. NMHTTP возможны такие исключения в случае если происходит чтение строковых свойств класса без проверки размера.

                                  1.3K

                                  12 ноября 2005 года

                                  Zephyr

                                  104 / / 03.05.2005

                                  Цитата:

                                  Originally posted by kot_
                                  Range Check Error генерируется как правило в случае если происходит попытка обращения к элементу массива по несуществующему индексу. NMHTTP возможны такие исключения в случае если происходит чтение строковых свойств класса без проверки размера.

                                  Извините конечно, но я не совсем понял… Тоесть вы сказали, что Параметр, отправленный мной компоненту NMHTTP слишком длинный (Ошибка выдаётся, при подставлении мной слишкого параметра в NMHTTP->Header(my_param))?
                                  А какова максимальная возможная длина параметра???

                                  1

                                  12 ноября 2005 года

                                  kot_

                                  7.3K / / 20.01.2000

                                  Цитата:

                                  Originally posted by Zephyr
                                  Извините конечно, но я не совсем понял… Тоесть вы сказали, что Параметр, отправленный мной компоненту NMHTTP слишком длинный (Ошибка выдаётся, при подставлении мной слишкого параметра в NMHTTP->Header(my_param))?
                                  А какова максимальная возможная длина параметра???

                                  Опиши, что и как ты передаешь. Мне воспроизвести ошибку не удалось в нормальных условиях.

                                  1.3K

                                  12 ноября 2005 года

                                  Zephyr

                                  104 / / 03.05.2005

                                  Цитата:

                                  Originally posted by kot_
                                  Опиши, что и как ты передаешь. Мне воспроизвести ошибку не удалось в нормальных условиях.

                                  Я делаю построковую выборку из текстового файла и подставляю эти значения (из выборки) в NMHTTP->Header. На какой-то строке цикл обрывается и выводится ошибка Range Check Error.

                                  1

                                  12 ноября 2005 года

                                  kot_

                                  7.3K / / 20.01.2000

                                  Цитата:

                                  Originally posted by Zephyr
                                  Я делаю построковую выборку из текстового файла и подставляю эти значения (из выборки) в NMHTTP->Header. На какой-то строке цикл обрывается и выводится ошибка Range Check Error.

                                  Приведи код — считывания из файла и записи в хедер.

                                  1.3K

                                  12 ноября 2005 года

                                  Zephyr

                                  104 / / 03.05.2005

                                  Цитата:

                                  Originally posted by kot_
                                  Приведи код — считывания из файла и записи в хедер.

                                  Код:

                                  TStringList* Strings = new TStringList;


                                  Strings->LoadFromFile(«somefile.txt»);
                                  int i=Strings->Count;

                                   for(int k=1; k<i; k++)
                                       {
                                           NMHTTP1->Head(URLEdit->Text
                                             +Strings->Strings[k]);
                                       }

                                  1

                                  13 ноября 2005 года

                                  kot_

                                  7.3K / / 20.01.2000

                                  Цитата:

                                  Originally posted by Zephyr

                                  Код:

                                  TStringList* Strings = new TStringList;


                                  Strings->LoadFromFile(«somefile.txt»);
                                  int i=Strings->Count;

                                   for(int k=1; k<i; k++)
                                       {
                                           NMHTTP1->Head(URLEdit->Text
                                             +Strings->Strings[k]);
                                       }

                                  Проверь содержание строкового массива. В целом код работает и подобных ошибок быть не должно. Например, содержание файла somefile.txt

                                  Код:

                                  /showthread.php?s=&postid=115401#post115401

                                  и урл — «http://forum.codenet.ru», возвращает нормальный заголовок, без всяких ошибок.
                                  Так же зайди в опции проекта, на закладку Паскаль и убери галочку в Range checking — посмотри какое исключение будет сгенерированно.

                                  1.3K

                                  13 ноября 2005 года

                                  Zephyr

                                  104 / / 03.05.2005

                                  Ошибка выдаётся на строке:

                                  NMHTTP1->Head(URLEdit->Text
                                  +Strings->Strings[k]);

                                  И ещё — где можно почитать доки по сетевому кодингу на ВС++В (в частности по компоненту NMHTTP)???

                                  Questions : Range check error in C++Builder (RAD Studio)

                                  2023-02-07T01:27:07+00:00 2023-02-07T01:27:07+00:00

                                  788

                                  I’ve been getting «Range check error»s while help uvdos c++ working with string arrays. To my help uvdos c++ understanding, this means I am using indexes help uvdos c++ that don’t exist in my array.

                                  My class and functions in my header file:

                                  AnsiString toBin(int n) {
                                      AnsiString zero = "0";
                                      int len;
                                      AnsiString result;
                                      while (n != 0) {
                                          result += (n % 2 == 0 ? "0" : "1");
                                          n /= 2;
                                      }
                                      len = result.Length();
                                      while (result.Length() < 8)
                                          result = zero + result;
                                      return result;
                                  }
                                                      
                                  int toInt(AnsiString bin) {
                                      int start = 1;
                                      int result = 0;
                                      for (int i = 0; i < 8; i++) {
                                          result += (int)bin[i] * start;
                                          start * 2;
                                      }
                                      return result;
                                  }
                                                  
                                  class enc_dec {
                                  private:
                                      AnsiString stext;
                                      AnsiString skey;
                                                  
                                  public:
                                      enc_dec(AnsiString t, AnsiString k) {
                                          stext = t;
                                          skey = k;
                                      }
                                                  
                                      AnsiString XOR() {
                                          if (skey == "") {
                                              Application->MessageBox(L"Error!", L"No Key", MB_OK);
                                              return "";
                                          }
                                          AnsiString cry = "";
                                          int key = skey[1] + 0;
                                          AnsiString keyBin = toBin(key);
                                          AnsiString temp = "";
                                  
                                          // AnsiString output[stext.Length()];
                                          std::vector<AnsiString>output;
                                          for (int i = 1; i < stext.Length(); i++) {
                                              temp = toBin(stext[i]);
                                              for (int j = 1; j < 8; j++) {
                                                  if (temp[j] == keyBin[j])
                                                      temp[j] = '0';
                                                  else
                                                      temp[j] = '1';
                                              }
                                              output.push_back(temp[i]);
                                          }
                                          for (int i = 0; i < stext.Length(); i++)
                                              cry += char(toInt(output[i]));
                                          return cry;
                                      }
                                  };
                                  

                                  My .cpp file:

                                  void __fastcall TForm1::Button1Click(TObject *Sender){
                                      enc_dec temp(Edit1->Text,Edit2->Text);
                                      temp.XOR();
                                  }
                                  

                                  The design:

                                  I found a mistake from before updating, The help uvdos c++ «Range Error» has not been resolved.

                                  Total Answers 1

                                  31

                                  Answers 1 : of Range check error in C++Builder (RAD Studio)

                                  Unlike standard C++ strings and arrays, post uvdos c++ which are 0-indexed, AnsiString is post uvdos c++ 1-indexed. Its valid character indexes post uvdos c++ are 1 <= N <= Length, not 0 <= post uvdos c++ N < Length as your for loops are post uvdos c++ written for.

                                  Also, in XOR(), return; should not post uvdos c++ compile, since XOR() is declared to post uvdos c++ return an AnsiString. You need to post uvdos c++ either return an actual value (ie return post uvdos c++ «»;) or else throw an exception instead post uvdos c++ of using Application->MessageBox().

                                  Also, AnsiString output[stext.Length()]; post uvdos c++ is not standard C++. You should use a post uvdos c++ std::vector or a System::DynamicArray post uvdos c++ for your array.

                                  0

                                  2023-02-07T01:27:07+00:00 2023-02-07T01:27:07+00:00Answer Link

                                  mRahman

                                  Понравилась статья? Поделить с друзьями:
                                • Range check error 7 wonders 2
                                • Randr query version returned error 1
                                • Random sampling error
                                • Random measurement error
                                • Ranch simulator ошибка fatal error