Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2005.08.07;
Скачать: [xml.tar.bz2];

Вниз

Качественный код   Найти похожие ветки 

 
Dust ©   (2005-07-20 12:54) [0]

Есть процедура.
смысл объяснять нужно?

Procedure ConvertStr (var str : Pchar; len : dword);
var pwch   : ^word;
   tmpstr : String;
begin
len:=len div 2;
pwch := Pointer(str);
for len := len-1 downto 0 do begin
       pwch^:= htons(pwch^);
       inc (dword(pwch),2);
       end;
tmpstr :=WideCharToString(PWideChar(str));
StrDispose (str);
str :=Pchar(tmpstr);
end;
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

len известно заранее.
так же есть комментарий моего знакомого по поводу этого кода


[11:33:08] <******> этот код является рассадником ошибок
[11:33:17] <******> я даже затрудняюсь посчитать сколько их тут
[11:33:28] <******> но две есть точно
[11:33:32] <******> причем грубые

<******> [11:30:44] <Dust> tmpstr :=WideCharToString(PWideChar(str));
<******> [11:30:48] <Dust> str :=Pchar(tmpstr);
<******> во-первых так делать нельзя
<******> [11:30:46] <Dust> StrDispose (str);
<******> во вторых так тем более
<Dust> а как будет правильно?

В общем вопрос так и повис, как будет правильно.


 
Alexander Panov ©   (2005-07-20 13:00) [1]

Что не работает-то?


 
Dust ©   (2005-07-20 13:01) [2]

всё работает


 
Digitman ©   (2005-07-20 13:16) [3]

нет, не работает.

убедись сам :

procedure TForm1.Button1Click(Sender: TObject);
var
s: string;
ptr: PChar;
begin
 s := "ABCD";
 ptr := pchar(s);
 ConvertStr(ptr, length(s));
 showmessage(s);
end;

оппонент тебе правильно сказал про "рассадник" и про грубые ошибки

так что рассказывай какова задача и что ты делаешь в каждой из строк, решая эту задачу в своей процедуре ..

приводи так же фрагмент вызова своей ф-ции, при котором это якобы "работает" ..


 
Dust ©   (2005-07-20 13:51) [4]

2Digitman
А я говорю работает, на вход подаётся Unicode строка с перевёрнутой последовательностью байт. Такую строку я получаю от SMPP сервера, вместе с её длинной.


len:=len div 2; //получаю длинну строки в словах
pwch := Pointer(str); //получаю указатель на первое слово в строке
pwch^:= htons(pwch^); //изменяю порядок байт в слове
inc (dword(pwch),2); //перхожу на следующее слово
tmpstr :=WideCharToString(PWideChar(str)); //конвертирую Unicode (WideString) в ANSIchar cp1251
StrDispose (str); //Освобождаю ранее выделенную память (не в этой функции)
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

фрагмент вызова, где это действительно нарботает:

...
       inc (i);
       Retrive_chars (smska.Short_message, smska.sm_length);
if fu then
  begin
   ConvertStr (smska.Short_message, smska.sm_length);
  end;
Result := smska;
.......

В функции Retrive_chars и происходит выделение памяти


 
Dust ©   (2005-07-20 14:07) [5]

2Digitman ткни пальцем в грубые ошибки


 
Alexander Panov ©   (2005-07-20 14:50) [6]

Dust ©   (20.07.05 14:07) [5]
2Digitman ткни пальцем в грубые ошибки


1. Вместо Len введи локальную переменную.
2. Вместо StrNew/StrDispose используй GetMem(ReallocMem)/FreeMem
3. Выделение/освобождение памяти в разных функциях чревато утечкой памяти.
4. Код не защищен блоками try..finally/except


 
han_malign ©   (2005-07-20 15:23) [7]

>ткни пальцем в грубые ошибки
Procedure ConvertStr (var str : Pchar; len : dword);
var pwch   : ^word;
  tmpstr : String;
begin
 len:=len div 2;
 pwch := Pointer(str);
 for len := len-1 downto 0 do begin
      pwch^:= htons(pwch^);
      inc (dword(pwch),2);
 end;
 tmpstr :=WideCharToString(PWideChar(str));
 StrDispose (str);
 str :=Pchar(tmpstr);
end;

"время жизни переменной" и "область видимости" - о чем нибудь говорит?

>В функции Retrive_chars и происходит выделение памяти
- а зачем перевыделять(если бы еще и перевыделялось) если байты в словах можно поменять прямо в исходном буфере? Что ты и делаешь, только три последние строки переменной - лишние(те самые грубые ошибки)...
вcего то:
Procedure ConvertStr (str : Pchar; len : dword);//!!! без var
var pwch   : PWORD absolute str;
begin
 len:=len div 2;
 for len := 0 to len-1 do begin
      pwch^:= htons(pwch^);
      inc(pwch);
 end;
end;


>Alexander Panov ©   (20.07.05 14:50) [6]
>1. Вместо Len введи локальную переменную.
- а так она какая?
>2. Вместо StrNew/StrDispose используй GetMem(ReallocMem)/FreeMem
- без разницы
>3. Выделение/освобождение памяти в разных функциях чревато утечкой памяти.
- да ну? Вот новость...
>4. Код не защищен блоками try..finally/except
- абсолютно лишняя, а в данном случае - и бесполезная вещь - AV - будет уже после этого кода.


 
Alexander Panov ©   (2005-07-20 15:30) [8]

han_malign ©   (20.07.05 15:23) [7]
- а так она какая?


А так это параметр.

han_malign ©   (20.07.05 15:23) [7]
- без разницы


Нет, не без разницы.Эти функции оставлены только совместимости, и в любой момент могут исчезунть при изменении версии.

han_malign ©   (20.07.05 15:23) [7]
- да ну? Вот новость...


Жалко, что для тебя это новость. А также новость то, что некая функция, в которой происходит освобождение памяти может:
1. По некоторому условию в программе вообще не выполниться.
2. Прерваться при возникновении Exception, и опять же не отработает функция освобождения памяти.


 
Alexander Panov ©   (2005-07-20 15:31) [9]

han_malign ©   (20.07.05 15:23) [7]
- абсолютно лишняя, а в данном случае - и бесполезная вещь - AV - будет уже после этого кода.


Читай выше.


 
Digitman ©   (2005-07-20 15:35) [10]

5. Время жизни лок.переменной равно времени жизни п/программы

Сославшись на tmpstr в этой строке

str :=Pchar(tmpstr);

ты сослался на строку, которая перестанет существовать сразу же по возврату из пройедуры

для грубых ошибок уже одного этого достаточно


> Alexander Panov ©   (20.07.05 14:50) [6]


по п.1 - это необязательно и здесь нет ошибки


 
Alexander Panov ©   (2005-07-20 15:42) [11]

Digitman ©   (20.07.05 15:35) [10]
по п.1 - это необязательно и здесь нет ошибки


Ну да, в грубую ошибку включать нельзя, но при изменениях кода это потенциальный источник ошибки.


 
Digitman ©   (2005-07-20 16:11) [12]

//строка, эмулирующая исх-данные для преобразования
const s: String = #0"A"#0"B"#0"C"#0"D"#0#0;
..

procedure ConvertStr(StrBuf: PWideChar; Len: Integer);
var
 tmpstr: String;
begin
 while Len > 0 do
   begin
     Dec(Len);
     PWordArray(StrBuf)[Len] := htons(PWordArray(StrBuf)[Len]);
   end;  
 tmpstr := WideCharToString(StrBuf);
 Move(PChar(tmpstr)^, StrBuf^, Length(tmpstr) + 1);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
str: PWideChar;
begin
 GetMem(str, 10);
 try
   Move(s[1], str^, 10);
   ConvertStr(str, 4);
   showmessage(pchar(str));
 finally
   FreeMem(str);
 end;
end;



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2005.08.07;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.034 c
14-1121326798
panov
2005-07-14 11:39
2005.08.07
Опросы.


14-1121430748
Igorek
2005-07-15 16:32
2005.08.07
Дельфимастер проснулся :)


14-1121329770
SergeyDon
2005-07-14 12:29
2005.08.07
работа поиска на сайте?


11-1104578339
N0th!ng
2005-01-01 14:18
2005.08.07
Помогите с KOL!


1-1121440783
dedelta
2005-07-15 19:19
2005.08.07
Подскажите как коректно внести и сохранить изменения в system.ini





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский