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

Вниз

проблема с локальной переменной типа Pchar   Найти похожие ветки 

 
alshtam   (2008-03-07 08:20) [0]

Здравствуйте, помогите разобаться пожалуста.
Есть две процедуры, одна вызывает другую:

procedure DatamapSave(var dm:TDataMap; s:string; cript:boolean;var version:Pchar);
var
 ss:Tfilestream;
begin
 ss := TFileStream.Create(dm.FileName, fmCreate);
 ss.Seek(0,soBeginning);
 saveStrStream(ss,version);
 dm.SaveToStream(ss);    //сдесь возникает ошибка
 if cript then
   EncryptStream(ss, ss.Size, "0");
 ss.Free;
end;

procedure saveStrStream(stri:Tstream; ss:Pchar);
var
 j:integer;
 s:Pchar;
begin
 {$o-}
 getmem(s,250);
 j:=strlen(ss);
 s:=Pchar(inttostr(j));
 stri.WriteBuffer(s^,3);
 stri.WriteBuffer(ss^,j+1);
 FreeMemory(s);       //если закоментить эту строку ошибки нет
end;

если закоментировать освобождение локальной переменной ошибки не возникает, но эт о вероятно приведет к утечкам памяти
Как освобожденная переменная могла привести к ошибке???


 
Palladin ©   (2008-03-07 08:22) [1]


>  s:=Pchar(inttostr(j));

это что такое? ты представляешь себе что это делает или просто так от балды написал?


 
alshtam   (2008-03-07 08:26) [2]

а как пправильно?
j:integer;
если написать s:=Pchar(j); то в s ниче не попадает


 
alshtam   (2008-03-07 08:30) [3]

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


 
Palladin ©   (2008-03-07 08:35) [4]

зачем ты это написал? с какой целью?


 
alshtam   (2008-03-07 08:37) [5]

с целью перевода переменной типа integer в string а затем в Pchar чтоб сохранить в файл.


 
Palladin ©   (2008-03-07 08:45) [6]


> к стати если ету строку закоментировать ошибка тоже не возникает,

с чего вдруг она возникнет, и зачем тебе вообще использовать Pchar? это какая то религия? а saveStrStream вообще бред какой то...

Procedure saveStrStream(stri:Tstream; Const s:String);
Var
n:Integer;
begin
n:=Length(s);
stri.WriteBuffer(n,SizeOf(n));
stri.WriteBuffer(s[1],n);
end;


ну и буду уж совсем до конца добрым

Function loadStrStream(stri:TStream):String;
Var
n:Integer;
Begin
stri.ReadBuffer(n,SizeOf(n));
SetLength(Result,n);
stri.ReadBuffer(Result[1],n);
End;


 
alshtam   (2008-03-07 08:50) [7]

:) спасибо большое, но все же не понятна природа ошбки? глюк какойто!


 
Palladin ©   (2008-03-07 08:56) [8]

глюки в первую очередь искать у себя в голове нужно

объясняю на пальцах

var
j:integer;
s:Pchar;
begin
{$o-} // зачем оптимизацию отключил? мешала?
getmem(s,250); // взяли память, теперь s у нас равна например $1000
j:=strlen(ss);
s:=Pchar(inttostr(j)); // функция inttostr вернула переменную типа string, которая сразу же была приведена к типу pchar и переменная s равна теперь $2000, потому что именно там была создана строка
stri.WriteBuffer(s^,3); // зачем то ты записал 3 байта от s, тоесть 000
stri.WriteBuffer(ss^,j+1);
FreeMemory(s);       //и тут ты зачем то освободил указатель на string, этого делать нельзя, за строками следят, и освобождаются они автоматически
end;


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


 
alshtam   (2008-03-07 09:26) [9]

оптимизацию отключил для трасировки(на время)

>  getmem(s,250); // взяли память, теперь s у нас равна например
> $1000
апочему 1000? разве по 4 байта на символ? ядумал 1байт
> // функция inttostr вернула переменную типа string, которая
> сразу же была приведена к типу pchar и переменная s равна
> теперь $2000, потому что именно там была создана строка

не непонял почему удвоилось все?

> //и тут ты зачем то освободил указатель на string, этого
> делать нельзя, за строками следят, и освобождаются они автоматически

не стой s она же типа Pchar и я под нее памят выделил потом Pchar и убил
> в результате ты кстати потерял где то в памяти 250 байт,
>  они ж не освободились...

тоже не понял когда.
если разъесниш буду оч благодарен


 
Palladin ©   (2008-03-07 09:41) [10]


> апочему 1000? разве по 4 байта на символ? ядумал 1байт

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

что происходит при вызове getmem. менеджер памяти (далее МП) выделяет кусочек памяти и возвращает его адрес. ты вызвал getmem(s,1000) например. МП нашел свободное пространство пометил это пространство как занято и присвоил указателю s адрес этого пространства. что происходит дальше. а дальше ты вызваешь функцию inttostr, которая тоже выделяет память (ей же нужно куда то заносить результат), и заполняет ее символьным представлением переданного числа. далее эта функция возвращает указатель на эту выделенную ею память и сохраняет этот указатель в переменной s, то есть предыдущее значение которое ты получил getmem потерялось (!). дальше. про действия inttostr я слишком утрировано рассказал что бы ты понял что переменная типа string это тоже указатель куда то в память. но на самом деле все гораздо сложнее. взятие  и освобождение памяти под строку выполняется автоматически. кусок памяти выделенный под string выглядит так:
[счетчик ссылок:4b][длинна строки:4b][данные:много байт]
потому просто так freemem для указателя на [данные] вызывать нельзя. а ты пытаешься.

понял?

ps. постарайся понять разницу между указателем и данными на которые он указывает.


 
alshtam   (2008-03-07 09:46) [11]

а теперь понял, спасибо за разьеснения!


 
Игорь Шевченко ©   (2008-03-07 10:24) [12]

" У некоторых людей отсутствует часть мозга, которая отвечает за понимание указателей"

(с) Джоэл Спольски



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

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

Наверх




Память: 0.48 MB
Время: 0.005 c
2-1205328745
simon26
2008-03-12 16:32
2008.04.06
Duplicate output destination ""


15-1203877668
Kerk
2008-02-24 21:27
2008.04.06
Интерпретация результата PASV


6-1184834764
Makhanev Alexander
2007-07-19 12:46
2008.04.06
sockets hook..


2-1205103782
Digital
2008-03-10 02:03
2008.04.06
Почему не ставится SaveDialog1.FileName ?


2-1204485733
Дмитрий Патрушев
2008-03-02 22:22
2008.04.06
Net-статистика





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский