Тема открыта по просьбе жителей Королевства и посвящена обсуждению вопросов оптимизации кода. Выставляйте свои лучшие и худшие тексты и не стесняйтесь их обсуждать. В споре рождается истина. Или, по крайней мере, оптимизация.
Всего в теме 737 сообщений
Добавить свое сообщение
Отслеживать это обсуждение
- Тестирование проекта. Отладка.
- Подводные камни
- Централизованная обработка ошибок
- Бета-тестирование
- Давайте учиться на ошибках.
- Почему программисты допускают ошибки?
- Автоматизированные тесты для GUI
- О системах контроля ошибок
№ 667 19-05-2009 14:12 | |
Ответ на »сообщение 665« (Geo)
___________________________
Лучший сопсоб -- арифметика указателей Весьма спорное утверждение, это какой-то Ц-шный, или скорее ассемблерный подход. Если Вы всёравно делали обёртку в виде своего класса, то можно было бы сделать методы Set и Get, которые бы работали со значением, а не с указателем.
При ближайшем рассмотрении все навороты оказались не нужны Вот это уже ближе к True :o) В подавляющем большенстве случаев оказывается тоже самое, поэтому вполне справедливо такое использование результата функции вызывает подозрение.
Ответ на »сообщение 666«
Например, принимать на вход TMemoryStream, а возвращать через Pointer его память TMemoryStream содержит размер и больше чем он может дать он не даст и не примит, а через Pointer можно что угодно записать с риском испортить содержимое памяти без сообщений об ошибке. Ну и опять же в большом проекте, кто его там разберет, надо, или не надо освобождать память...
№ 666 19-05-2009 11:21 | |
Ответ на »сообщение 664« (Cepгей Poщин)
___________________________
Всё-таки есть в этом что-то противоестественное. Допустим, мы выделяем память внутри GetCellPointer и ссылку на эту область памяти мы не имеем, а значит получаем утечку памяти.
А что, если память не выделять? Например, принимать на вход TMemoryStream, а возвращать через Pointer его память. Все предельно корректно, но вызов - такой же "странный".
№ 665 19-05-2009 09:46 | |
Ответ на »сообщение 664« (Cepгей Poщин)
___________________________
>>> Допустим, мы выделяем память внутри GetCellPointer и ссылку на эту область памяти мы не имеем, а значит получаем утечку памяти
Ну, так ежу ясно, что все надо делать с головой, а не только прическу :-)
Я сейчас уже, если честно, подзабыл, где и как именно у меня этот код выполз. Что-то я пытался мухлевать с доступом к отдельным пикселям битмапа, пытаясь изобразить из этого что-то двумерномассивообразное. Этакий аналог Canvas.Pixels, но без тормозов. Суцть в том, что память уже была выделена и зафиксирована, но мне нужно было по введенным координатам получить нужный участок памяти. Лучший сопсоб -- арифметика указателей, то есть по введенным значениям коордиант вычисляем смещение в области данных битмапа и возвращаем типизированный указатель на этот участок памяти. Все это потом было обернуто в класс, чтобы доступаться действительно как к массиву (через индексное свойство). Вот в паре методов, реализующих у меня что-то такое и выскочило.
При ближайшем рассмотрении все навороты оказались не нужны (с DDB код не работал, а с DIB и TCanvas.Pixels работает без тормозов), но вот забавный код в голове остался ;-)
№ 664 19-05-2009 09:20 | |
Ответ на »сообщение 663« (Geo)
___________________________
Всё-таки есть в этом что-то противоестественное. Допустим, мы выделяем память внутри GetCellPointer и ссылку на эту область памяти мы не имеем, а значит получаем утечку памяти. Возможно по этой причине GetMem не функция а процедура, чтобы не было соблазна писать PInteger(GetMem(4))^ := 12345; Если же мы просто каким-то образом поучаем адрес, то было бы более идеалогически верно создать тип для осуществления доступа к двоичным данным: type
TXXX = packed record
...
...
GetCell: integer;
...
end;
var XXX: TXX;
XXX.GetCell := ...
№ 663 19-05-2009 08:55 | |
Ответ на »сообщение 662« (Сергей Перовский)
___________________________
>>> А, собственно, в чем дикость?
>>> Слева "куда положить", справа "что положить".
Да все нормально. Я не говорю, что это неправильно. Более того, я этот код вообще на автомате написал. Но потом дико рубанула по глазам функция, стоящая слева в операторе присваивания. Имя функции -- оно большое (особенно, если с параметрами), а крышечка маленькая-маленькая, поэтом при беглом просмотре в глаза не бросается. Поэтому глаз и спотыкается :D
№ 662 19-05-2009 05:47 | |
Ответ на »сообщение 661« (Geo)
___________________________
А, собственно, в чем дикость?
Слева "куда положить", справа "что положить".
Нормальный оператор присваивания.
№ 661 19-05-2009 05:35 | |
Я поспешил и привел не самый выразительный пример. Действительно, у меня функция была с параметрами, что выглядит более... э-э-э... наглядно. Что-то типа:
function GetCellPointer(X,Y : Integer) : PInteger;
begin
end;
GetCellPointer(15,20)^:=180;
Абсолютно правильно (никакие AV не возникнут, если функция написана корректно), но дико и непривычно для глаз*
№ 660 17-05-2009 08:48 | |
Возможно более наглядный пример:
var
a,b: Integer;
function GetPointer(t: Boolean): PInteger;
begin
if t then
Result := @A
else
Result := @B
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
GetPointer(False)^ := 2;
GetPointer(True)^ := 3;
ShowMessage(IntToStr(A)+' '+IntToStr(B));
end;
Запись типа "GetPointer^ := 20" выполняется так: сначала вызывается функция GetPointer потом по адресу который она вернула (благодаря операции ^) записывается значение 20.
Вот если б было "GetPointer := 20" тогда был бы AccessViolation, если б конечно компилятор позволил бы так написать.
№ 659 16-05-2009 01:51 | |
Ответ на »сообщение 658« (Комбриг)
___________________________
>>> А писать такое вне тела функции еще ужаснее - 100% гарантированный AccessViolation
var
A: Integer;
function GetPointer: PInteger;
begin
A := 10;
Result := @A;
end;
procedure Test;
begin
GetPointer^ := 20;
ShowMessage(IntToStr(A));
end;
№ 658 16-05-2009 00:57 | |
Ответ на »сообщение 657« (Антон Григорьев)
___________________________
Ответ на »сообщение 656« (Комбриг)
___________________________
Будьте внимательнее - SomeFunc^:=10 там написано вне тела функции SomeFunc, поэтому заменить SomeFunc на Result здесь нельзя.
А писать такое вне тела функции еще ужаснее - 100% гарантированный AccessViolation
Добавить свое сообщение
Отслеживать это обсуждение
Дополнительная навигация: |
|