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

Вниз

Проблема с PChar   Найти похожие ветки 

 
Giemgo   (2003-04-11 21:53) [0]

Вот мой код:

procedure TForm1.Button1Click(Sender: TObject);
var P:PChar;
begin
P:="Hello";
showmessage(P); //Здесь стоит брекпойнт
end;


По брекпоинту в окне CPU перехожу по адресу переменной P - вижу там полную фигню. Почему ?


 
Giemgo   (2003-04-11 21:57) [1]

Как понимаю, при P:="Hello" компилятор выделяет 5 байт под слово и записывает его в память. @P указывает на первый символ.

В CPU windows символ на который указывает P вовсе не "H" и последующие вовсе не "ello"


 
Palladin ©   (2003-04-11 21:58) [2]

а что ты там ожидал увидеть?
строку чтоли...

под указатель надо память выделять... этому тебя в школе не учили?


 
Giemgo   (2003-04-11 22:11) [3]

Как понимаю, при P:="Hello" компилятор выделяет 5 байт под слово и записывает его в память


 
Sha ©   (2003-04-11 22:13) [4]

2Giemgo (11.04.03 22:11)
неправильно понимаешь.


 
Palladin ©   (2003-04-11 22:18) [5]


> Giemgo (11.04.03 22:11)

хахаха
откуда пришло к тебе это понимание?
странно даже както...

на всякий случай

конвертация string в pchar

var
s:string;
p:pchar;

s:="Hello";
p:=PChar(s);


 
Giemgo   (2003-04-11 22:25) [6]

Palladin, хорошо. Тогда если я неправ, почему showmessage(P); все таки выводит "Hello", а не мусор ?


 
Palladin ©   (2003-04-11 22:43) [7]

круто...

P:="Hello";
0044DBAC B8C8DB4400 mov eax,$0044dbc8

вывод
"Hello" в сегменте данных и в P устанавливается ссылка на него,
для строковых констант присваивание будет работать...
для строковых переменных нет...

и кстати ты не прав по поводу "вижу там полную фигню"
я нормальный Hello увидел...


 
Palladin ©   (2003-04-11 22:49) [8]

тьфу
ночь, глючу уже

вот это считать глупостью и не читать...

> для строковых констант присваивание будет работать...
> для строковых переменных нет...


в P устанавливается адрес строки "Hello"
память для P не выделяется...

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


 
Palladin ©   (2003-04-11 22:53) [9]

опять сглючил...
в общем память для PChar именно не выделяется это точно...
хватит с меня... ушел спать..


 
Giemgo   (2003-04-11 23:09) [10]

Я что-то запутался:

а что ты там ожидал увидеть?
строку чтоли...


и потом:

и кстати ты не прав по поводу "вижу там полную фигню"
я нормальный Hello увидел...


Я неправильно написал - не в том смысле, что память выделяется, а сама строка как константа пишется, потом P начинает указывать на начало этой строки. Это по идее.

Но как я говорил у меня проблема.

Давайте подробнее:

остановка по брекпоинту showmessage(P);

Открываю WatchList, узнаю адрес переменой P

Открываю окно CPU windows, там внизу в левом окне в сплывающем меню нажимаю Goto address. Ввожу узнанный мною адес P

Вижу полную фигню, а не Hello

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


 
Anatoly Podgoretsky ©   (2003-04-12 00:09) [11]

Не видать никакой необходимости в использовании PChar вместо string


 
Fantasist.   (2003-04-12 01:09) [12]


> Открываю WatchList, узнаю адрес переменой P


По адресу переменной P, лежит сама переменная P, как это не покажется вам странным. А строка лежит по адресу, который записан в переменной P. Память, в данном случае, выделяется в сегменте памяти, а в P просто записывается адрес этой выделенной памяти.


 
Giemgo   (2003-04-12 09:33) [13]

Fantasist, блин, как же я сам не догадался. Спасибо!

Только вот все равно не получается :(

Смотрю, указывает переменая P на байт FC, затем идут F6 12 00

Перехожу в памяти по адресу $FC F6 12 00 - опять фигня :(((


 
anbezr   (2003-04-12 10:45) [14]

а ты поставь точку останова не begin, и когда сработает вызови CPU window - сразу все поймешь. проблема в том, что глобальные константы, коей является "Hello", и локальные, коей является P адресуются по разному: первые через DS:EBX, а вторые через смещение в SS:ESP.


 
anbezr   (2003-04-12 10:52) [15]

пардон, не правильно подобрал темин, хотя суть это не меняет. не глобальные константы, а константы,описанные вне функции.


 
Giemgo   (2003-04-12 12:00) [16]

Плохо понимаю, при чем тут вообще смещения ?
Я же нахожу не по смещению относительно сегмента данных, а по адресу переменной.

И если остановить на begin, то P еще будет не инициализирована


Так... во время написания потыркался и, блин, понял, что туплю по страшному. Ведь указатель - это 4-х байтовое целое, соответственно, указатель указывает на младший байт в адресе строки :)

В общем, он указывал на $FC F6 12 00, а сам то адрес в памяти значит $00 12 F6 FC


 
anbezr   (2003-04-12 12:24) [17]

ну так что, получилось? увидел строчку по [p]


 
Giemgo   (2003-04-12 16:46) [18]

Не знаю что такое [p], но строчку увидел, когда обратился по адресу записанном в байтах, на которые указывает P. В общем, как сказал Fantasist.


 
Giemgo   (2003-04-12 20:07) [19]

Anatoly Podgoretsky
" Не видать никакой необходимости в использовании PChar вместо string"

Вы так считаете ? А если нужно передать в функцию по ссылке PChar ? Как например для функции sendto второй параметр.

Покажите мне как можно использовать string в качестве второго параметра для sendto


 
Morfein ©   (2003-04-12 20:14) [20]


sendto(..., "строковая константа", ... );


устраивает? :)
можно и по другому...


var
s : string;
begin
s:="строковая переменная";
sendto(..., pointer(s), ... );



 
Giemgo   (2003-04-12 22:53) [21]

Morfein, хорошо написал, нда.

sendto(..., "строковая константа", ... );
устраивает? :)


Нет, не устраивает. Ты сам то хоть попробуй так сделать

sendto(..., pointer(s), ... );

И чего ?! И куда интересно указывают байты Hell в hex форме ?


 
NA ©   (2003-04-12 23:53) [22]


> Giemgo (12.04.03 20:07)
> Anatoly Podgoretsky
> "Не видать никакой необходимости в использовании PChar вместо
> string"
> Вы так считаете ? А если нужно передать в функцию по ссылке
> PChar ? Как например для функции sendto второй параметр.
> Покажите мне как можно использовать string в качестве второго
> параметра для sendto


Согласен с предыдущим оратором совершенно.

PChar (string) - и без проблем. Иногда - @String[1] (когда допустимо).

Я вопщем не против PChar как явления. Но! Вот, скажем, я когда-то себе в назидание сохранил такой кусок кода (из прынцыпу нашел - половину вырезал для облегчения восприятия):


.........
Open := StrAlloc (256); Open := PChar (Dlg_Open.FileName);
Save := StrAlloc (256); Save := PChar (Dlg_Save.FileName);
.........
try CopyFile (Open, Save, false) except
.........
case Dlg_Open.FilterIndex of
1 : Open := PChar (ChangeFileExt (Open, TV_ext));
2 : Open := PChar (ChangeFileExt (Open, TV_bak));
end;
.........
case Dlg_Save.FilterIndex of
1 : Save := PChar (ChangeFileExt (Save, TV_ext));
2 : Save := PChar (ChangeFileExt (Save, TV_bak));
end;
.........
try CopyFile (Open, Save, false) except
Error ("Не удалось скопировать связанный список погрузки")
.........


Так вот, к моменту копирования второго файла в PChar"ах вместо нормальных имен оказывался тааакой бардак, что я с тех пор стараюсь вообще нигде в преобразованиях типов их не использовать. Или сам заглючишь - увлечешься "совместимостью", или компилятор пошутит.


 
Giemgo   (2003-04-13 00:01) [23]

Плохо понял вышенаписанное. Я уже указал где я не могу использовать string вместо PChar. Если в данном случае стринг использовать можно - покажите как!


 
NA ©   (2003-04-13 00:20) [24]

Куда уж проще.


 
Giemgo   (2003-04-13 13:20) [25]

Что куда уж проще ?

Вы можете ПРИВЕСТИ пример вызова sendto со вторым параметром string,а не PChar ???!! Анатолий Подгорецкий сказал, что нет необходимости использовать PChar, если есть string. Ну а вот я не понимаю, как его здесь можно использовать!

sendto(..., "строковая константа", ... );

даже не откомпилируется. Не знаю о чем думал автор сообщения

sendto(..., pointer(s), ... );

Откомпилируется, конечно. Только вот ЧТО получится...


 
Anatoly Podgoretsky ©   (2003-04-13 13:33) [26]

А назови такое место, где ты не можешь использовать string вместо array[] оf char?
Есть много вариантов использования, например Pointer(S) или Pchar(S), именно так и можешь передавать в любую функцию.


 
Anatoly Podgoretsky ©   (2003-04-13 13:37) [27]

О какой функции sendto ты говоришь, по моему хелпу, второй параметр этой функции Integer


 
NA ©   (2003-04-13 14:45) [28]


> Giemgo (13.04.03 00:01)
> Плохо понял вышенаписанное.


Вчера перечитывал пейджер... много думал... :)))

1) PChar (string)
2) @string[1]

Если тебе и первый непонятен, второй еще долго не понадобится. Интересно вообще, как ты пишешь что-то там "на чистом API" (это из соседней твоей темы) при таких знаниях.


 
Giemgo   (2003-04-13 15:20) [29]

Anatoly Podgoretsky, функция описана в win32sdk.hlp
Объявление есть в модуле winsock

Повторюсь, что второй параметр надо передать по ссылке, то есть:

function sendto(s: TSocket; var Buf; len, flags: Integer; var addrto: TSockAddr;
tolen: Integer): Integer; stdcall;


PChar(s) не подходит. Pointer(s) фигню выдает. Тем более, я так думаю, так нельзя писать, потому что Ponter(s) вернет указатель на структуру string, которая недокументирована

NA, лично я удивляюсь как ты при своих знаниях находишь смелость что-то советовать другим. Это относится как и к моей соседней ветке, так и к этой. Уважаемый, вы сначала сами попробуйте сделать как написали, а потом уж говорите. Ок ?


 
Anatoly Podgoretsky ©   (2003-04-13 15:38) [30]

А вот другое объявление
function SendTo: (var buf; bufsize: integer; ToAddr: TSockAddr; flags:
Поэтому надо конкретно указывать о каком SendTo идет речь или просто привести объявление функции.

В данном случае, это указатель на абсолютно любой абстрактный буфер, абсолютно любой .
В качестве его может быть статически распреденный, массив, динамический одномерный массив, динамически выделенная память, строка или что нибудь дрогое обладающее адресом и протяженностью.
И PChar(S) Pointer(S) полностью подходят, третий вариант передачи адреса, это операция взятия адреса @buf[n], для строки точно также. Естественно что во всех случаях "массив" должен существовать.


Твое представления об string абсолютно не верны, не знаю на чем они базируются. И Pointer и PChar вернут адрес первого байта буфера


 
NA ©   (2003-04-13 15:41) [31]

Легко, уважаемый:

if RegQueryValueEx (Key, FoldName, nil, @D1, @Folder[1], @D2) = Error_Success


...необходимую инициализацию строки и реестра перед, надеюсь, допишете сами? При Ваших-то знаниях? :)))


 
Giemgo   (2003-04-13 16:17) [32]

Anatoly Podgoretsky, в свою очередь хочу спросить - а где вы достали такое объявление ?

Если " И PChar(S) Pointer(S) полностью подходят"

то почему компилятор мне сообщает:
[Error] Unit1.pas(44): Constant object cannot be passed as var parameter

Насчет Pointer(s). Ведь вы не будете спорить, что string, если понимать под ним AnsiString - это не просто последовательность символов ? Вот поэтому я и усомнился в правильности Pointer(s)


NA, я вообще-то говорил про sendto, вам не кажется ?!. И еще раз, специально для тебя повторяю. СПЕЦИАЛЬНО. ПОСЛЕДНИЙ РАЗ.

Параметр должен передаваться по ССЫЛКЕ.


 
NA ©   (2003-04-13 20:59) [33]

По-моему, тебе уже не один раз ответили.


 
Giemgo   (2003-04-13 22:19) [34]

PChar(s) не подходит - я уже писал.

Просто Pointer(s) делает все неправильно. Ладно, возможно у меня ошибка в коде, еще поразбираюсь.

Остался вопрос, Pointer(s) и @s[1] это документированные ссылки ? То есть, могу я расчитывать, что в следующих версиях дельфи они будут работать также, даже если поменяется формат string ?


 
jack128 ©   (2003-04-13 23:02) [35]

function sendto(s: TSocket; var Buf; len, flags: Integer; var addrto: TSockAddr;
tolen: Integer): Integer; stdcall;

При таком объявлении функции нужно писать так
var s : string;
begin
...
sendto(MySocket,s[1],...);
...
end;
Второй параметр это не указатель на буффер куда положут данные, а сам буффер. Думаю вам нужно понять разницу между указателем и ссылкой.

> Pointer(s) и @s[1] это документированные ссылки ?

По поводу первого варианта не скажу, а второй то точно всегда будет работать.


 
default ©   (2003-04-13 23:18) [36]

function Length_(const S: String): LongWord;
begin

Result := LongWord(Pointer(LongWord(@S[1]) - 4)^)

end;

от этого ты наверно совсем офигеешь...
фигню ты говоришь насчёт того если формат поменяется -
указатель-то идёт на первый байт данных строки (не на байты её длины не на
счётчик ссылок(это для типа string)...)как бы формат не меняли данные-то останутся...
вот приведённая выше Length_ легко может "захромать" при изменении формата String поскольку
читает 4 байта длины строки типа String поэтому если раз-ки Delphi в следующей версии захотят
"переместить" эти данные то эта ф-ия работать будет не верно либо вообще вылетит с AV хотя это
маловероятно...понятно?!


 
default ©   (2003-04-13 23:35) [37]

procedure TForm1.Button1Click(Sender: TObject);
var
Str: PChar;
begin

Str := "12345";
Caption := Char(Pointer(LongWord(Str) + 2)^); // Form1.Caption = "3"

end;

procedure TForm1.Button1Click(Sender: TObject);
var
Str: PChar;
begin

Str := "12345";
if Pointer(Str) = @Str[0] then Caption := "Эквивалентно";

end;

надеюсь уж это всё прояснит...
помогло?


 
NA ©   (2003-04-14 00:48) [38]

> LongWord(Pointer(LongWord(@S[1]) - 4)^)

ЖЖЖ>8 - [= - =]


:-)))


 
Giemgo   (2003-04-14 11:38) [39]

jack128 © (13.04.03 23:02)

Да, вероятно в этом все дело. Вы не могли бы мне объяснить разницу между указателем и ссылкой ?

Просто я вот тут покопался. Оказывается PChar не указывает на данные, он указывает на область памяти, где записан адрес этих данных. Вот блин.

И если функции SendTo передать PChar, то она отправляет именно этот адрес. Честно говоря, я в недоумении, ведь по идее PChar это указатель на Char... а он указывает на адрес, по которому этот PChar расположен :(((((


 
Anatoly Podgoretsky ©   (2003-04-14 12:01) [40]

Так не оказывается, по определению он должен указывать на строку ASCIIZ, но может указывать на что угодно, это уже в твоих руках.
В Дельфи 1 PChar был именно указателем на Char, теперь на строку.



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

Текущий архив: 2003.04.24;
Скачать: CL | DM;

Наверх




Память: 0.58 MB
Время: 0.012 c
14-77078
Andrey Filatow
2003-04-06 20:49
2003.04.24
update Delphi 7


1-76976
Alexander1966
2003-04-11 16:12
2003.04.24
Delphi-йский аналог объявленных констант C++Builder


1-76873
Альф
2003-04-14 15:27
2003.04.24
Как запретить перерисовку ВСЕГО окна ?


1-76879
dimonf
2003-04-14 16:39
2003.04.24
Народ, как создать перечесляемый тип, для своего компанента?


1-76995
Deadlock
2003-04-13 03:17
2003.04.24
Сортировка компонентов в Components