Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2002.12.16;
Скачать: CL | DM;

Вниз

Компоненты 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;
Скачать: CL | DM;

Наверх




Память: 0.58 MB
Время: 0.014 c
1-51715
Oleg__
2002-12-06 11:16
2002.12.16
TListBox


4-52001
Lexa1900
2002-11-03 23:29
2002.12.16
Как получить hwnd активного окна?


4-52008
Обсолютный Ноль
2002-11-03 21:40
2002.12.16
Ламерский вопрос


14-51886
Bublichek
2002-11-22 15:52
2002.12.16
ОПРОС


1-51695
avsh
2002-12-05 22:03
2002.12.16
Помогите