Форум: "Базы";
Текущий архив: 2002.12.16;
Скачать: [xml.tar.bz2];
ВнизКомпоненты ADO в сервисе Win32 Найти похожие ветки
← →
iZEN (2002-11-27 13:07) [40]Было: AllNames: TStringList;
Стало: AllNames: array of String;
← →
BlackTiger (2002-11-27 13:09) [41]Что-то странное в компонентах VCL все-таки есть. И это не глюки программиста. Я подозреваю, что Делфа проводит какую-то НЕЯВНУЮ инициализацию чего-то внутри и этой инициализации не происходит в таких специфичных приложениях как консольные и сервисы. При этом хелпы просто умалчивают про это (впрочем много о чем еще).
В книгах про ТАКИЕ вещи тоже не пишут, так как авторы зачастую сами ничего в этом не понимают. Ответ знают только борландовцы и люди, которые сами бились (и успешно!) с такими проблемами. Подход, который подходит (калабурчик-с) для разработки стандартных (оконных) приложений, абсолютно не применим при создании сервисов и консолей - тут надо копать глубже, но не всегда понятно в какую сторону.
Вот! Мое личное мнение.
← →
Zelius (2002-11-27 14:15) [42]А у тебя не выскакивает ошибка типа "List index out of bounds" ?
Судя по коду, у тебя есть несколько потенциальных мест для возникновения ошибок.
← →
iZEN (2002-11-27 14:45) [43]/**Zelius © (27.11.02 14:15)
А у тебя не выскакивает ошибка типа "List index out of bounds" ?
*/
Нет. Всё глухо. Отладчик не жалуется...
← →
iZEN (2002-11-27 14:51) [44]Этот конструктор использует локальную функцию, которая читает файл в буфер. Представляет его как байтовый поток (Stream), из которого берутся строки длиной 20 символов (константа
lenName = 20;
).
Переполнения никакого быть не может: изначально вычисляется и устанавливается длина массива с "хвостиком" (SetLength(AllNames, mis.Size div lenName + lenName);
).
Это решает проблему выхода за границы массива.
Переменнаяj
служит для подсчёта "полноценных" строк.
← →
Zelius (2002-11-27 14:58) [45]Такой вопрос, тебе удалось полноценно пройтись отладчиком по этому коду? То есть я хочу сказать, что есть шанс, что какое-то исключение ты просто не увидел, иногда отладчик сразу убегает в другой кусок кода. Например, в первом варианте кода, ты забывал передать в AllNames тот кусок строки, который был последним в файле и не был кратным 20! Однако j у тебя указывал на то что она есть и при присвоенни в Names это последней строки вылезал эксепшн! Этот кусок кода я смоделировал у себя.
← →
iZEN (2002-11-27 15:09) [46]Вы имеете ввиду строчку
SetLength(Names, j+1);
?
Здесь происходит задание длины массива на 2 элемента больше (! т.к. j увеличивается 2 раза: послеInc(j);
и в этом месте).
Хотя действительно можно обойтисьSetLength(Names, j-1);
- по длине массива AllNames.
Или даже так:
SetLength(Names, High(AllNames) - Low(AllNames) + 1);
(Кстати, спасибо за намёк на уловку:), лишние два элемента массива надо бы исключить)
В любом случае, выход за границы не происходит, но количество элементов, естественно, выходит больше чем есть. "Лишние" элементы пустые. Я по шагам всё проверил.
← →
Zelius (2002-11-27 15:21) [47]Попробуй, пожалуйста, такой код, в нем я постарался исключть по максимуму возможные подводные камни, хотя один там еще остался:
constructor TTSArchiv.Create(const NamesFileName, ValuesFileName: TFileName);
procedure FillNames();
//Запонение массива Именами ТС
var fis: TFileStream;
k: Integer;
s: AnsiString;
c: Byte;
AllNames: TStringList;
begin
fis := nil;
AllNames := nil;
try
fis := TFileStream.Create(NamesFileName, fmOpenRead or fmShareDenyNone);
AllNames := TStringList.Create();
fis.Position := 0;
while fis.Position < fis.Size do
begin
fis.Read( c, 1);
Inc(k);
if (c >= 32) then s := s + ANSI(c);
if (k = 20) and (s <> "") then
begin
AllNames.Add(s);
s := "";
k := 0;
end;
end;
if s <> "" then AllNames.Add(s);
SetLength( Names, AllNames.Count);
for i := 0 to AllNames.Count-1 do
Names[i] := AllNames[i];
finally
FreeAndNil(AllNames);
FreeAndNil(fis);
end;
end;
begin
inherited Create();
FillNames();
end;
← →
iZEN (2002-11-27 15:24) [48]Вот так вернее (ошибся насчёт "задание длины массива на 2 элемента больше"):
...
finally
if (Assigned(AllNames)) then begin
SetLength(Names, j);
for i := Low(Names) to High(Names) do
Names[i] := AllNames[i];
...
Массив AllNames имеет длину, превышающую число значимых строк (j - счётчик строк).
← →
iZEN (2002-11-27 15:34) [49]Для Zelius © (27.11.02 15:21).
Спасибо за код.
НО!
В консольном приложении: строчкаs
не заносится вAllNames.Add(s);
. ХОТЬ ТРЕСНИ!!!
Под отладчиком в окне "Локальные переменные" видим:
...
AllNames: ();
НИЧЕГО НЕТ!
Хотя AllNames <> nil;
← →
iZEN (2002-11-27 15:38) [50]Вот такие чудеса...однако.
← →
iZEN (2002-11-27 15:46) [51]Дополнение к iZEN © (27.11.02 15:34).
s
имеет допустимое значение на всех стадиях функции.
← →
Zelius (2002-11-27 15:50) [52]Остается только одно, по Станиславскому - НЕ ВЕРЮ :))
Попробуй вставь в код дополнительные переменные простого типа и присвой их в интересующих тебя местах, типа после заполнения массива перед SetLength( Names, AllNames.Count); поставь k := AllNames.Count и s := Allnames.CommaText и помотри, что они буду значить...
← →
Zelius (2002-11-27 15:51) [53]Должен заявить, что данный когд не имеет никакого отношения к консольности!!! Если что-то не работает, то надо искать причину в другом...
← →
iZEN (2002-11-27 15:55) [54]Дополнение к iZEN © (27.11.02 15:34).
s
имеет допустимое значение на всех стадиях функции.
← →
iZEN (2002-11-27 16:11) [55]На Zelius © (27.11.02 15:50).
И это пробовал. Думаете я первый раз попадаю в "передряги"?
Непонятно одно: почему AllNames.Add(s); не отрабатывает, даже исключений нет.
Странно. Весма странно.
На Zelius © (27.11.02 15:51).
/**Должен заявить, что данный когд не имеет никакого отношения к консольности!!! Если что-то не работает, то надо искать причину в другом...*/
А к чему он имеет значение? В оконном прил. работает, в консольном не работает? Есть идеи?
← →
iZEN (2002-11-27 16:14) [56]Попробовал бы я так в Java поставить вопрос - меня бы на смех подняли.
Ну нет там таких заморочек! Всё прозрачно, если используешь стандартные библиотечные объекты (да и свои тоже).
← →
Zelius (2002-11-27 17:04) [57]а ты ставил на AllNames.Add(s) брякпойнт? Ты заходил в дебагере внутрь этого метода? если нет, то попробуй... и поставь брякпойнт в секции finally! Если код сразу перейдет туда, значит был эксепшн... Мне кажется, что возможное объяснение происходящего это эксепшн при открытии файла... Больше мыслей нет... Все должно работать...
← →
iZEN (2002-11-28 08:07) [58]Для Zelius © (27.11.02 17:04).
Ну естественно, я же уже не мальчик.
В секцию finally переход осуществляется только после прочтения всего файла и "якобы-занесения" всех строк в AllNames.Add(s). То есть всё происходит без исключений и всё читается (это я вижу при пошаговой отладке), но AllNames оказывается пустым всегда, даже не nil!
Предположение: в Delphi в конструкторе объектов исключения не могут выбрасываться до завершения конструирования (проглатываются? тихие исключения?).
Вы-то сами можете попробовать: обычный текстовый файл, в котором число символов кратно 20. Есть собственная функция ANSI() (очень простая), переводящая чимвол кодировки DOS866 в WIN1251, но она Вам не нужна для эксперимента.
P.S. Задача вообще-то решена с использованием дин.массива. Так что проехали?
← →
ЮЮ (2002-11-28 09:09) [59]>Под отладчиком в окне "Локальные переменные" видим:
AllNames: ();
НИЧЕГО НЕТ!
Хотя AllNames <> nil;
А AllNames[0], AllNames[AllNames.Count - 1] ??
Это у динамического массива в отладчике видно (("1")("2")), а StringList так не посмотришь
Страницы: 1 2 вся ветка
Форум: "Базы";
Текущий архив: 2002.12.16;
Скачать: [xml.tar.bz2];
Память: 0.56 MB
Время: 0.007 c