![]() |
|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
||||
|
||||
![]() Никак не могу врубиться, а почему если оставить FillChar(P^, SizeOf(TData), 0) закомментированным, то выдаёт любимый Access Violation?
Код:
unit TestDataUnit; interface uses Forms; type TForm1 = class(TForm) procedure FormShow(Sender: TObject); private { Private declarations } public { Public declarations } end; // TForm1 = class(TForm) TData = packed record FText: String; end; // TData = packed record var Form1: TForm1; P: Pointer; implementation {$R *.dfm} procedure TForm1.FormShow(Sender: TObject); begin P := GetMemory(SizeOf(TData)) ; // FillChar(P^, SizeOf(TData), 0); with TData(P^) do SetString(FText, PChar(nil), 30); end; // procedure TForm1.FormShow(Sender: TObject) end. |
#2
|
||||
|
||||
![]() Код:
type PData = ^TData; TData = record Text: String; end; var p: PData; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin p:=GetMemory(SizeOf(TData)); ZeroMemory(p, SizeOf(TData)); // необязательно вовсе p^.Text:='hello'; end; procedure TForm1.FormDestroy(Sender: TObject); begin p^.Text:=''; FreeMemory(p); end; procedure TForm1.Button1Click(Sender: TObject); begin ShowMessage(p^.Text); end; Пишу программы за еду. __________________ |
#3
|
||||
|
||||
![]() Ну во первых у меня Delphi 7, я там ZeroMemory не видел. Во-вторых, я полагаю, FillChar(P^, SizeOf(TData), 0) делает то же, что и ZeroMemory(p, SizeOf(TData)). Но вот для чего оно в данном контексте нужно? Знать бы как работает SetString... Исходника я не нашёл у себя. Мож в инете?
|
#4
|
||||
|
||||
![]() у меня тоже Delphi 7, о чем написано в профиле.
Код:
var s: String; begin SetString(s, PChar('hello'), 5); ShowMessage(s); end; Пишу программы за еду. __________________ |
#5
|
||||
|
||||
![]() Да, извиняюсь, про Delphi 7 просмотрел. А для чего тут-то SetString? Можно просто s := 'hello'. Но вопрос был не об этом. Вопрос: почему без FillChar выдаёт Access Violation? И, кстати, если написать так
Код:
procedure TForm1.FormShow(Sender: TObject); var s: String; begin s := 'hello'; ShowMessage(s); P := GetMemory(SizeOf(TData)) ; // FillChar(P^, SizeOf(TData), 0); with TData(P^) do SetString(FText, PChar(nil), 30); end; // procedure TForm1.FormShow(Sender: TObject) |
#6
|
||||
|
||||
![]() ZeroMemory, если мне не изменяет мой склероз вызывает FillChar
Некоторые программисты настолько ленивы, что сразу пишут рабочий код. Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты. |
#7
|
|||
|
|||
![]() Потому что строка в Дельфи - это объект с автоматическим временем жизни и подсчётом ссылок. В константно1 строке счётчик равен -1, во вновь созданной - 0;
Любое присваивание в строку - это: 1)Проверить, на Nil старый указатель. 2)Если там Nil, то перейти на 6) 3)Проверить счетчик ссылок, если там не 1, то перейти на 5) 4)Освободить память, занимаемую строкой, перейти на 6) 5)Если счётчик не -1, то уменьшить счётчик 6)Собственно присвоить новый указатель 7)Проверить на Nil новый указатель 8)Если там Nil, то Exit 9)Проверить счётчик. Если там не -1, то увеличить счётчик. В многопоточном режиме добавляются Interlocked операции Строковые локальные переменные процедур и поля классовых переменных после конструкторов инициализируются Nil`ами. GetMemory осуществляет только заказ памяти и ничем его не прописывает. Поэтому на шаге 1) у Вас будет не Nil, а на шаге 4) - Access Violation. |
Этот пользователь сказал Спасибо icWasya за это полезное сообщение: | ||
BBBCat (14.03.2013)
|
#8
|
||||
|
||||
![]() Сорри, электричество вырубали у нас
![]() Ну наконец-то внятный ответ! А то все вопрос читают по диагонали ![]() 1)На Nil старый указатель не проверяется. 3)Счетчик ссылок не смотрится, а сразу устанавливается на единицу 7)Проверить на Nil новый указатель и 8)Если там Nil, то Exit - вот здесь-то и должно родиться EOutOfMemory Про Access Violation ни слова. Т.е. исходя из хэлпа должно работать без FillChar(P^, SizeOf(TData), 0), а исходя из практики - так как вы отписали. Такая ситуация немного напрягает. А вдруг там ко всему вышесказанному ещё что-то есть. Поэтому хотелось бы точно знать, как SetString работает. В смысле на исходник глянуть. А у вас откуда все эти сведения? Вот ещё что забыл: из сообщения icWasya рождается объясниние, почему во втором из приведённых мной здесь коде всё нормально срабатывает при добавлении Код:
s := 'hello'; ShowMessage(s); Последний раз редактировалось BBBCat, 14.03.2013 в 12:43. |
#9
|
|||
|
|||
![]() Как я сказал, эта процедура вызывается при ВСЕХ присваиваниях строк.
Как раз старый указатель на Nil проверяется всегда. А поскольку у Вас там мусор - то и ошибка. А в хелпе написано, что делается с НОВОЙ строкой. То есть создаётся новая строка, а если не получилось(Nil), то и вызывается EOutOfMemory. По поводу того, что при выполнении шамашских действий начинает работать. Мусорный указатель не всегда приводит к Access Violation. Или приводит, но не сразу. Или ошибка выскочит где-нибудь через час работы программы на ровном месте. В Вашем случае этот указатель мог совпасть с указателем на вот эту строку 'hello'. Поскольку она константная, счётчик у неё равен -1, а для таких строк FreeMem не вызывается. И запомните - если программа работает правильно(или Вам так кажется), это не значит, что в ней нет ошибок. |
#10
|
||||
|
||||
![]() Согласен, программа без глюков - это значит глюк у программиста
![]() |
#11
|
||||
|
||||
![]() Я с вас сильно удивляюсь господа.
Исходник SetString не судьба посмотреть? Там 3 строчки всего, и сразу все понятно становится. Некоторые программисты настолько ленивы, что сразу пишут рабочий код. Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты. |
#12
|
||||
|
||||
![]() Цитата:
Извиняюсь, не с этого начал, но во втором сообщении точно написал ![]() Да и ZeroMemory я чёй-та не найду. Где он? Последний раз редактировалось BBBCat, 14.03.2013 в 14:25. |
#13
|
||||
|
||||
![]() Код:
procedure _SetString(s: PShortString; buffer: PAnsiChar; len: Byte); begin Byte(s^[0]) := len; if buffer <> nil then Move(buffer^, s^[1], len); end; Некоторые программисты настолько ленивы, что сразу пишут рабочий код. Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты. |
#14
|
||||
|
||||
![]() Не, ну это-то я уже видел. Это ж для ShortString. Там и вопроса-то такого не возникло бы. А вот что для String?
|
#15
|
||||
|
||||
![]() Цитата:
Код:
procedure ZeroMemory(Destination: Pointer; Length: DWORD); begin FillChar(Destination^, Length, 0); end; Пишу программы за еду. __________________ |
Этот пользователь сказал Спасибо NumLock за это полезное сообщение: | ||
BBBCat (14.03.2013)
|