![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Ошибка при освобождении памяти выделенной переменной Pointer
ford © (2009-05-04 23:33:00)Помогите найти ошибку.
вот кусок кода
Type TData=Array[1..5] of Int64;
TRecStruct=record
...
Data:TData;
end;
function TDataFile.ReadData(p:Int64; bCount:Integer):Pointer;
Var buf:Pointer;
f:TFileStream;
rec:TRecStruct;
Begin
...
f.Seek(p,soFromBeggining);
...
GetMem(buf,SizeOf(TData));
f.Read(rec,SizeOf(TRecStruct));
move(Pointer(@rec.data[1])^,Pointer(Int64(buf))^,SizeOf(TRec));
bCount:=SizeOf(TRec)
result:=buf;
End;
читается из файла структура, выделяется память пременной куда
копируются считанные данные и возвращается указатель на эти данные
далее в другой процедуре
Procedure Append(s:String);
Var ss:Pointer;
buf:Array of Int64;
dd:^Int64;
p:Int64;
bCount:Integer;
...
//читаем данные и получаем указатель на них
ss:=DataF.ReadData(p,bCount);
//в данной процедуре я хочу их интерпретировать как массив Int64
buf:=ss; //<----
Buf[0]:=buf[0]+1;
//dd:=ss;
//dd^:=dd^+1;
//записываем данные обратно в файл в пизицию Р
DataF.WriteData(p,ss,SizeOf(TRec));
//освобождаем память
FreeMem(ss);
end;
-----------------
ничего особенного, читаем данные из файла с позиции P в буфер
пытаемся использовать данные как массив Int64
изменяем первый элемент массива
записываем данные обратно в файл и собственно освобождаем указатель
пару раз отрабатывает нормально
на третий разрушаются переменные которые были переданны процедуре
например S изначально имеет значение 'ПРИВЕТ'
после строки buf:=ss; её значение изменяется на
что-то типа 'ПРИВЕТ'+#0+#0+'W'+#0+#0.....
и при попытке освободить память в строке
FreeMem(ss);
вылетает AcessViolation
ежели я закоментирую строки с buf:=ss; buf[0]:=buf[0]+1;
и откоментирую другие там где dd:=ss; dd^:=dd^+1;
то все проходит нормально хоть вызывай эту процедуру 1000 раз
:((
я понимаю что гдето я переписываю не ту память
но немогу найти хоть тресни
помогите, подскажите где ошибка
Игорь Шевченко (2009-05-05 11:43:00) [1]ford © (05.05.09 02:29) [9]
> и к стати я от тебя не увидел ни какого красивого решения
> данной задачи
вообще-то решение задачи должно быть от тебя, вроде как твоя задача.
Servy (2009-05-05 03:27:00) [2]> в Си это делается просто без всяких вывертов и наворотов
>
> там ежели это указатель то разадресовывай его как хочешь
Ты не поверишь, в Делфи ровно также.
> Массив это такой указатель
Массив - это массив, и ничего более.
> динамический массив это другой указатель
Динамический массив в делфи - это особый тип данных, финализируемый компилятором. Назвать его просто указателем - неверно.
> т.е. ты не смотри что массив в памяти храниться последовательно
>
> что в первом что в другом случае и что собственно говоря
> что там что там переменная это не что иное как адрес перового
> элемента
Есть существенная разница - на что указывает этот, как вам нравится его называть, указатель. Как уже упоминалось, динамический массив - особый тип данных, и если вы не работаете с ним так, как ожидает компилятор - предполагается, что вы знаете, что делаете. В вашем случае - вы, видимо, не знаете. А должны бы знать, в хелпе все хорошо описано.
Все просто: если вам нужен указатель - используйте указатель. Если вам нужен динамический массив - используйте динамический массив. Если вам нужен указатель на массив - используйте указатель на массив.
> неее ты сломай мозг :) вывернись наизнанку
У плохого мастера инструмент виноват :).
Ваш код написан в сишном стиле - непонятные двухбуквенные переменные, кучи действий без комментариев и необходимости в них. Для примера, было бы интересно узнать, зачем могло понадобится Pointer(Int64(buf))^ - приводить указатель к Int64, а потом назад. В общем, это WriteOnly код - написал, работает, забыл. Другому человеку (или самому себе через полгода) в нем разбираться - дело очень неблагодарное, так что и мне заниматься им не слишком-то охота ^_^.
> в реале пришлось сделать
> for i:=1 to BCount div SizeOf(Integer) do
> Integer(Integer(ss)+SizeOf(Integer)*(i-1))^:=10
Этот код даже не скомпилируется, так как тип Integer нельзя разыменовать.
Возможно, вам нужно что-то вроде:
type
TInt64Array = array [0..268435454] of Int64;
PInt64Array = ^TInt64Array;
var
Buf: PInt64Array;
В этом случае, Buf будет указателем на массив, чего вы, судя по всему, и хотели. Однако, в вашем коде вполне могут быть другие ошибки, который при таком стиле написания обнаружить будет ой как непросто. Но это уже ваше дело :).
> вообще прикольно наверное, пробежав вопрос, не вникнув в
> КОД указанный выше и описание к нему
> ляпнуть абы-что, типа "пометить" - "тут был Вася"
Мне показалось, что пост [8] кратко и по-существу описывает возникшую у вас проблему - то, что под динамическим массивом вы понимаете что-то иное, а не то, что разработчики делфи описали в хелпе в разделе dynamic arrays. Впрочем, вам некого в этом винить, кроме как самого себя ^_^.
ford (2009-05-05 02:36:00) [3]
> sniknik © (05.05.09 01:26) [8]
>
> > То есть, ты присваиваешь некий свой pointer динамическому
> массиву
> он думает что это одно и то же. начитаются разного... ->
>
> http://www.delphimaster.ru/cgi-bin/forum.pl?id=1241089539&n=18
> > вполне себе динамический массив.
вообще прикольно наверное, пробежав вопрос, не вникнув в КОД указанный выше и описание к нему
ляпнуть абы-что, типа "пометить" - "тут был Вася"
:))
ford (2009-05-05 02:29:00) [4]
> sniknik ©
в Си это делается просто без всяких вывертов и наворотов
там ежели это указатель то разадресовывай его как хочешь
а тут млин
Массив это такой указатель
динамический массив это другой указатель
т.е. ты не смотри что массив в памяти храниться последовательно
что в первом что в другом случае и что собственно говоря что там что там переменная это не что иное как адрес перового элемента
неее ты сломай мозг :) вывернись наизнанку
в реале пришлось сделать
for i:=1 to BCount div SizeOf(Integer) do
Integer(Integer(ss)+SizeOf(Integer)*(i-1))^:=10
это так, для разминки, чтобы присвоить всем прочтенным элементам массива значение 10
:))
и к стати я от тебя не увидел ни какого красивого решения данной задачи
sniknik (2009-05-05 01:26:00) [5]> То есть, ты присваиваешь некий свой pointer динамическому массиву
он думает что это одно и то же. начитаются разного... ->
http://www.delphimaster.ru/cgi-bin/forum.pl?id=1241089539&n=18
> вполне себе динамический массив.
ford (2009-05-05 00:35:00) [6]получилось только таким образом
Type TBigArray=Array[1..1000] of Int64;
и в программе
TBigArray(ss^)[1]:=TBigArray(ss^)[1]+1;
выглядит конечно белокоренно но работает
:(
ford (2009-05-05 00:23:00) [7]
> То есть, ты присваиваешь некий свой pointer динамическому
> массиву и удивляешься, что происходят ошибки ?
>
> Я бы не удивлялся.
а как тогда ??
со структурами все классно
TAnyStruct(ss).Field:=100;
а вот с массивами .....
Игорь Шевченко (2009-05-05 00:19:00) [8]То есть, ты присваиваешь некий свой pointer динамическому массиву и удивляешься, что происходят ошибки ?
Я бы не удивлялся.
ford (2009-05-05 00:14:00) [9]
> TRect не понятно откуда взялось.
не TRec ессесно а TData
уже три варианта переписал
не тот кусок вставил
но смысл не меняется
> неужели нельзя попроще
незнаю может и можно
есть файл хранилище в котором хранятся структуры и массивы
и класс контейнер для всего этого добра который просто читает кусок файла и передает дальше
а кто просил тот и решает как его интерпретировать
т.е. контейнер инкапсулирует в себе все функции чтения записи/данных
поэтому в контейнере запись файла содержит в себе некоторую информацию необходимую для него и собственно сами данные которые записываюся
структура TRecStruct
и собственно данные которые туда пишутся поле Data
я уже упростил и сделал просто массив целых
и передаю туда и читаю из него
palva (2009-05-05 00:05:00) [10]Правда к делу это отношения не имеет.
palva (2009-05-05 00:03:00) [11]
> Да и TRect не понятно откуда взялось.
Пардон, Как раз TRect понятно, что такое. У вас нигде не описанный идентификатор TRec.
palva (2009-05-04 23:55:00) [12]
> move(Pointer(@rec.data[1])^,Pointer(Int64(buf))^,SizeOf(TRec));
Честно говоря, напрягают такие параметры, неужели нельзя попроще. Да и TRect не понятно откуда взялось.