![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
FillChar для строки [D7, XP]
Dmitry_177 © (2007-05-26 02:25:00)Как правильно выполнить FillChar для строки?
Если выполнить так:
var
s: string;
...
FillChar(s, SizeOf(s), #0);
ИМХО очистится не сама строка, а указатель на нее..
Вот так правильно ли будет?
var
s: string;
...
FillChar(PChar(s)^, Length(s), #0);
Dmitry_177 (2007-05-26 14:48:00) [21]Anatoly Podgoretsky, ладно бог с ней с этой строкой.. а как тогда структуру очищать без FillChar-а?
Anatoly Podgoretsky (2007-05-26 14:45:00) [22]> Loginov Dmitry (26.05.2007 14:27:28) [28]
Использовать FillChar самому себе вредить, а потом удивляемся откуда знаменитый buffer overflow
Насколько я помню в .NET компилятор грубо обругает за подобные вольности.
Loginov Dmitry (2007-05-26 14:27:00) [23]> просто на сколько я знаю "#0"-это именно нулевой символ,
> а "0" - это символ 48
Ноль - он и в африке ноль!
Dmitry_177 (2007-05-26 14:24:00) [24]просто на сколько я знаю "#0"-это именно нулевой символ, а "0" - это символ 48.. Может какое-то да тратится время на перевод из 0 в #0? Вот я и спросил может сразу уж "#0" задавать..
Но если так у меня встречный вопрос, а если мы очищаем не строку а какую-то структуру? Где есть и строки и числа? тут уже что лучше "#0" или "0"?
Кстати как лучше структуры очищать? Что передавать первым и вторым параметром? Вот к примеру есть такая структура:
Tabc = packet record
a: integer;
b: integer;
c: string или pchar или array [0..MAX_PATH-1] of Char;
end;
Что лучше передавать в Fillchar первым параметром? abc или Pointer(abc)?
P.S. насчет параметра c, незнаю как string и pchar, я использую array [0..MAX_PATH-1] of Char;
Однокамушкин (2007-05-26 14:01:00) [25]
> Ведь как тут уже говорилось Pointer(str) при пустой строке
> вернет nil.
Но ведь вот какая штука: Length(str) при ёэтом вернёт 0... А FillChar, он достаточно умный, чтобы при нулевой длине не обращаться к памяти, на которую указывает первый параметр... Так что ничего страшного, отдельно s<>'' можно не проверять...
> А еще что лучше передавать третьим параметром? ведь если
> передавать "#0" и "0" строка в обоих случаях очищается..
А без разницы... Для процессора что то - ноль, что это - ноль...
Dmitry_177 (2007-05-26 13:51:00) [26]а если к примеру есть строка, и мы не знает есть ли в ней что-то или она пустая.. как тогда лучше делать? Ведь как тут уже говорилось Pointer(str) при пустой строке вернет nil. Вот так?
if str <> '' then
FillChar(Pointer(str), Length(str), #0);
А еще если Length-ем не вариант пользоваться, то чем тогда лучше?
> и Length(s) я бы не использовал, поскольку наверняка имеется
> переменная, где эта длина записана.
У меня нету такой переменной..
А еще что лучше передавать третьим параметром? ведь если передавать "#0" и "0" строка в обоих случаях очищается..
Loginov Dmitry (2007-05-26 13:43:00) [27]> А как тогда можно "побыстрее" очистить строку ?
> Я использовала FillChar(s[1], cbStrLen, #0) и была счастлива
> :)
Очищай так и далее, и будь счастлива. Тем более, что не вижу практического смысла применения операции FillChar к строкам (ну ни разу практическине вознакала такая потребность)
Однокамушкин (2007-05-26 12:53:00) [28]
> Riply © (26.05.07 12:12) [22]
> А как тогда можно "побыстрее" очистить строку ?
А так, как мы уже тут говорили...
FillChar(Pointer(s), cbStrLen, #0)
Быстрее, наверное, только на асемблере...
Riply (2007-05-26 12:12:00) [29]> [21] Однокамушкин (26.05.07 10:43)
> а ещё обращение к отдельному символу в строке приводит к неявному вызову UniqueString
Вот тебе и раз :(
А как тогда можно "побыстрее" очистить строку ?
Я использовала FillChar(s[1], cbStrLen, #0) и была счастлива :)
Однокамушкин (2007-05-26 10:43:00) [30]
> palva © (26.05.07 09:58) [19]
> Я в таких случаях вообще обхожусь без приведения
> FillChar(s[0], Length(s), #0);
Видимо, имелся ввиду s[1]... Но это тоже корректно только если s<>'', а то будет то же av... а ещё обращение к отдельному символу в строке приводит к неявному вызову UniqueString, чтобы не повредились переменные, ссылающиеся на ту же строку, а это тоже дополнительная работа для процессора...
Loginov Dmitry (2007-05-26 10:11:00) [31]> Вот, нашёл...
thanks! Буду знать!
palva (2007-05-26 09:58:00) [32]Однокамушкин (26.05.07 09:18) [12]
> но зато немного сэкономим на вызове _LStrToPChar - пустячок, а приятно...
Согласен.
Я в таких случаях вообще обхожусь без приведения
FillChar(s[0], Length(s), #0);
и Length(s) я бы не использовал, поскольку наверняка имеется переменная, где эта длина записана.
Однокамушкин (2007-05-26 09:45:00) [33]Вот, нашёл...
http://www.rsdn.ru/article/Delphi/dynarrays.xml#ENF
Однокамушкин (2007-05-26 09:42:00) [34]
> Loginov Dmitry © (26.05.07 09:31) [16]
>
> Дак я ж про то говорю, что в консольном приложеним "в данном
> случае" AV-то как раз и не будет.
Кажись, разобрался... Тут не в консольном приложении дело, а в том, что переменные глобальные... Например, такой код даёт av:
{$APPTYPE CONSOLE}
procedure Test;
var
s1, s2: String;
begin
s1 := 'qwerty';
s2 := s1;
writeln(s2); // 'qwerty'
FillChar(PChar(s1)^, Length(s1), #0);
writeln(s2);
readln
end;
begin
Test
end.
В неконосльном приложении такой код тоже не даёт ошибки
var s1, s2:string;
procedure TForm1.Button1Click(Sender: TObject);
begin
s1 := 'qwerty';
s2 := s1;
FillChar(PChar(s1)^, Length(s1), #0);
Button1.Caption:=s2
end;
Но если сделать переменные локальными, av будет...
Смутно припоминаю, что когда-то видел статью, где об этом говорилось... сейчас попробую найти...
Loginov Dmitry (2007-05-26 09:31:00) [35]> Читал, просто решил сказать то же самое немного другими
> словами
Дак я ж про то говорю, что в консольном приложеним "в данном случае" AV-то как раз и не будет.
Однокамушкин (2007-05-26 09:27:00) [36]
> Loginov Dmitry © (26.05.07 09:23) [14]
>
> [10] читать будем?
Читал, просто решил сказать то же самое немного другими словами, раз palva не согласился сразу и стал возражать... В чём проблема-то?
Loginov Dmitry (2007-05-26 09:23:00) [37]> Неожиданным последствием в данном случае будет access violation,
> т.к. вы пытаетесь модифицировать сегмент кода...
[10] читать будем?
Однокамушкин (2007-05-26 09:21:00) [38]
> palva © (26.05.07 09:11) [11]
> Loginov Dmitry © (26.05.07 08:59) [10]
> Это я не в курсе. Я написал пример, который демонстрирует,
> как я предполагаю, неожиданные для автора последствия.
Неожиданным последствием в данном случае будет access violation, т.к. вы пытаетесь модифицировать сегмент кода...
Однокамушкин (2007-05-26 09:18:00) [39]
> FillChar(PChar(s)^, Length(s), #0);
В этой строке приведение к PChar неправильно... Правильнее приводить к Pointer, потому что PChar(string) на самом деле не приведение типов, а неявный вызов функции _LStrToPChar. Если s<>'', то Pointer(s)=PChar(s), а вот если s='', то Pointer(s)=nil, а PChar(s)<>nil, он указывает на символ #0, размещённый в сегменте кода... Тут конечно без разницы, какой будет указатель, если длина всё равно ноль, но зато немного сэкономим на вызове _LStrToPChar - пустячок, а приятно...
palva (2007-05-26 09:11:00) [40]Loginov Dmitry © (26.05.07 08:59) [10]
Это я не в курсе. Я написал пример, который демонстрирует, как я предполагаю, неожиданные для автора последствия.