Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Работа с указателями и динамической памятью, передача массивов между функциями 
:(
    Опции темы
Geniebal
Дата 16.11.2011, 08:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 35
Регистрация: 13.5.2010

Репутация: нет
Всего: нет



Здравствуйте! 
Для передачи динамического массива между функциями хотелось бы использовать указатели. Ниже код:
Код

function func(mas: Pointer):boolean;
 var
 ...
 body_mass: Pointer;
 ...
 begin
  ...
   
   While Start>0 do
        begin
         body_mass:=nil;
         if Resident_Attribute(mas,Start,body_mass, Body_len,Attr_Len,Attr_Type) then
            begin
              ...                
              Start:=Next_Atribute(mas,start,Attr_Len); // если есть след аттр
            end
         else
           if Non_Resident_Attribute(mas,Start,body_mass,run_data_list_len,Attr_Len, Real_body_Size, Alloc_Body_Size,Attr_Type) then
              begin
                ...
                Start:=Next_Atribute(mas,start,Attr_Len);
              end;
         FreeMem(body_mass);
         end;


функции :
Код

function Resident_Attribute(mas: Pointer; Start_Attr_Byte: integer; var Body_Attr: Pointer; var Body_Len: integer; var Attr_Len: integer;var type_attr: integer): boolean;
 var
 b: string;
 Name_len, i: integer;
 begin
  ...
   Body_Attr:=GetMemory(Body_Len);
   for i := 0 to Body_Len-1 do
        PArray(Body_Attr)^[i]:=PArray(mas)^[Start_Attr_Byte+2*Name_len+24+i]; // тело атрибута
   Result:=true;
 end;

и
Код

function Non_Resident_Attribute(mas: Pointer; Start_Attr_Byte: integer; var run_data_list: Pointer; Var run_data_list_len: integer; var Attr_Len: integer; var Real_Attr_Body_Size: int64; var Alloc_Body_Atrr_size: int64;var type_attr: integer): boolean;
var
 b: string;
 i, Name_Len: integer;
begin
...
  run_data_list:=GetMemory(run_data_list_len);
 for i := 0 to run_data_list_len-1 do
     PArray(Run_data_list)^[i]:=PArray(mas)^[Start_Attr_Byte+2*Name_len+64+i]; // косячит тут!!!!
  Result:=true;

в функциях PArray это 
Код

ТArray = array of byte;
  PArray = ^TArray;


Собственно причина моего сообщения: после 2-х успешных разов завершения функции Residen_atribute (т.е. память выделяется, массив заполняется и т.д.), прохождение функции Non_Resident завершается ошибкой связаной с обращением к недоступному участку памяти! (Строка, где ывылетает эта ошибка помечена комментарием в коде) 
Мб я что то не правильно делаю?:( помогите плз, а то всю голову сломал уже...  

PM MAIL   Вверх
MetalFan
Дата 16.11.2011, 09:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 16
Всего: 128



Отдели мух от котлет.
Не используй дин.массивы и ручное выделение памяти.
p.s. Либо объяви 
Код

TArray = array [0..0] of byte;


Это сообщение отредактировал(а) MetalFan - 16.11.2011, 09:14


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Geniebal
Дата 16.11.2011, 09:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 35
Регистрация: 13.5.2010

Репутация: нет
Всего: нет



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

TArray = array [0..0] of byte;

не получится

Это сообщение отредактировал(а) Geniebal - 16.11.2011, 09:29
PM MAIL   Вверх
MetalFan
Дата 16.11.2011, 09:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 16
Всего: 128



Цитата(Geniebal @  16.11.2011,  09:24 Найти цитируемый пост)
не получится

Почему? отключаем Range Checking и все должно работать.

Это сообщение отредактировал(а) MetalFan - 16.11.2011, 09:43


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Geniebal
Дата 16.11.2011, 09:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 35
Регистрация: 13.5.2010

Репутация: нет
Всего: нет



Всмысле 
Цитата

отключаем Range Checking


если я тупо пишу TArray = array [0..0] of byte, то выдается ошибка типо - попытка обратится к элементу массива вне его диапазона.
и насколько я понимаю TArray = array [0..0] of byte это массив на 1 элемент. или я опять что то путаю?

PM MAIL   Вверх
MetalFan
Дата 16.11.2011, 10:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 16
Всего: 128



мм... счас, накидаю пример.

Код

type
  PArray = ^TArray;
  TArray = array [0..0] of Byte;

procedure TForm1.btnClick(Sender: TObject);
var
  lPtr: PArray;
  i: Integer;
  lSum: Cardinal;
begin
  lPtr := GetMemory(50);
  try
    lSum := 0;
    for i := 0 to 49 do
    begin
      lSum := lSum + lPtr^[i];
    end;
  finally
    FreeMemory(lPtr);
  end;
end;


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

Это сообщение отредактировал(а) MetalFan - 16.11.2011, 10:31


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Geniebal
Дата 16.11.2011, 14:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 35
Регистрация: 13.5.2010

Репутация: нет
Всего: нет



сделал как ты написал, получилось равноценно тому что было в начале у меня - ошибка с обращением хз куда
PM MAIL   Вверх
MetalFan
Дата 16.11.2011, 20:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 16
Всего: 128



Ну ищи тогда ошибку в своем коде.
Твой подход по работе с указателем на дин.массив в корне неверный.
Предложенный мной подход вполне жизнеспособен.
Видимо где-то вылет за границы выделенной памяти или нечто подобное.


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Geniebal
Дата 17.11.2011, 10:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 35
Регистрация: 13.5.2010

Репутация: нет
Всего: нет



Цитата

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

Почему? Делаем указатель - выделяем память на определенный размер - образаемся к памяти через указатель как к массиву... Что не правильно?
PM MAIL   Вверх
CodeMonkey
Дата 17.11.2011, 11:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 16
Всего: 89



http://www.gunsmoker.ru/2009/01/blog-post.html - аж 4 варианта кода.

Добавлено через 3 минуты и 55 секунд
Цитата(Geniebal @  16.11.2011,  10:59 Найти цитируемый пост)
если я тупо пишу TArray = array [0..0] of byte, то выдается ошибка типо - попытка обратится к элементу массива вне его диапазона


Можно как-то так:

Код

type
  TArray = array [0..MaxInt div SizeOf(TElem) - 1] of TElem;


Мог ошибиться на единичку в правой границе, но смысл понятен.

Добавлено через 6 минут и 13 секунд
Цитата(Geniebal @  17.11.2011,  11:11 Найти цитируемый пост)
Почему? Делаем указатель - выделяем память на определенный размер - образаемся к памяти через указатель как к массиву... Что не правильно? 


Потому что ты не выделил память под массив. Ты выделили память под данные массива.

Наводящий вопрос: где хранится число, сколько элементов в массиве?

Учим мат-часть: http://www.transl-gunsmoker.ru/2009/09/blog-post.html


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Geniebal
Дата 18.11.2011, 11:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 35
Регистрация: 13.5.2010

Репутация: нет
Всего: нет



Цитата

Потому что ты не выделил память под массив. Ты выделили память под данные массива.

Наводящий вопрос: где хранится число, сколько элементов в массиве?


При выделении мы же указываем требуемый размер? или это не то?
и тогда просто гениальный вопрос: почему АНАЛОГИЧНАЯ функция Resident_atribute РАБОТАЕТ?
PM MAIL   Вверх
CodeMonkey
Дата 18.11.2011, 11:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 16
Всего: 89



Цитата(Geniebal @  18.11.2011,  12:12 Найти цитируемый пост)
При выделении мы же указываем требуемый размер?


Читай мат-часть по указанным ссылкам. Динамический массив - это не блок памяти. Динамический массив имеет служебный заголовок, который ты игнорируешь.

Код
type
  TArray = array of Integer;
  PArray = ^TArray;

var
  Ptr: PArray;
begin
  Ptr := AllocMem(50 * SizeOf(Integer));
  Caption := IntToStr(Length(Ptr^)); // внимание, вопрос: откуда в этой строчке возникнет число 50? Где оно хранится?
end;


Цитата(Geniebal @  18.11.2011,  12:12 Найти цитируемый пост)
и тогда просто гениальный вопрос: почему АНАЛОГИЧНАЯ функция Resident_atribute РАБОТАЕТ? 


Так кубики выпали.



--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Geniebal
Дата 23.11.2011, 16:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 35
Регистрация: 13.5.2010

Репутация: нет
Всего: нет



Спасибо! Разобрался.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • 99% ответов по WinAPI можно найти в MSDN Library, оставшиеся 1% здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.0828 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.