Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2016.05.08;
Скачать: [xml.tar.bz2];

Вниз

Пятничная головоломка от Розыча   Найти похожие ветки 

 
Rouse_ ©   (2015-08-20 21:22) [0]

program PtrTest;

{$APPTYPE CONSOLE}

uses
 SysUtils;

type
 TTestClass = class
 private
   FFirst, FSecont, FThird: Integer;
 public
   function GetParamValue(Index: Integer): Integer;
 end;

{ TTestClass }

function TTestClass.GetParamValue(Index: Integer): Integer;
begin
 Result := -1;
 case Index of
   0: Result := FFirst;
   1: Result := FSecont;
   2: Result := FThird;
 end;
end;

var
 A: TTestClass;
 B: array [0..2] of Int64;
 C: array of Integer;
 D: string;
 pA, pB, pC, pD: Pointer;
begin
 try
   A := TTestClass.Create;
   try
     SetLength(C, 3);
     D := StringOfChar(#0, 3);

     pA := @A;
     pB := @B;
     pC := @C;
     pD := @D;

     { TODO : Реализовать код здесь...
       используя только указатели pA, pB, pC и pD
       произвести следующие изменения
       1. Поле FThird класса А должно принять значение 1
       2. B[2] должно равнятся двум
       3. С[2] должно равнятся трем
       4. D[3] должно равнятся четырем
     }

     // выводим результат

     Writeln(A.GetParamValue(2));
     Writeln(B[2]);
     Writeln(C[2]);
     Writeln(Byte(D[3]));
   finally
     A.Free;
   end;
 except
   on E: Exception do
     Writeln(E.ClassName, ": ", E.Message);
 end;
 Readln;
end.


 
Rouse_ ©   (2015-08-20 21:29) [1]

Опс, забыл нюанс - она решается без использования дебагера.
(Можно и с помощью его, но смысл теряется)


 
Игорь Шевченко ©   (2015-08-20 21:31) [2]

Зачем ?


 
Rouse_ ©   (2015-08-20 21:33) [3]

А зачем вообще нужны задачи? :)
Данный пример показывает как человек умеет работать с памятью и понимает ее адресацию.


 
Pavia ©   (2015-08-20 21:47) [4]

А что надо сделать?
И честно не понимаю как. Т.е. какие выражения можно использовать и какие операции?


 
DayGaykin ©   (2015-08-20 21:55) [5]


       TTestClass(pA^).FThird := 1;
       PInt64Array(pB)^[2] := 2;
       PIntegerArray(pC)^[2] := 3; // Не работает. Как найти @C[0] по @C не знаю. Разница между ними большая.
       PString(pD)^[3] := Char(4);



 
Pavia ©   (2015-08-20 22:06) [6]


> А зачем вообще нужны задачи? :)Данный пример показывает
> как человек умеет работать с памятью и понимает ее адресацию.

Не понятно что вы хотите увидеть?
Вирт Н. учил структурировать свой код. Поэтому использовать указатели тут не разумно. Тем более так. Если вы хотите посмотреть кто как использует арифметику указателей. Так это от задачи зависит.

Лично я делаю так.


type // Вспомогательные типы
 PColor=^TColor;

 PAColor=^TAColor;
 TAColor=array [0..65535] of TColor;  // Своеобразный хак. магические константы могут быть любыми, но порой лучше от 0.

procedure Filter(var Goal:TBitmap; bp:TBitmap);
var
InRow:PAColor; // Указатель на массив Цветов.
OutRow:PAColor;

begin

...
   InRow:=Bp.Canvas.ScanLine[y];
   Inc(PColor(InRow),X); // Смещение указателя на X*SizeOf(TColor)

   a:=0;
   for i:=-1 to 1 do  
      a:=a+InRow[i];  {Смещение указателя на I*SizeOf(TColor) относительно X}
   OutRow[x]:=a;
 ...
 Inc(PByte(OutRow), LineLen); // Смещение на заданное число байт. Переход к другой строке. Не обязательно кратный SizeOf(TColor).  
...


 
DayGaykin ©   (2015-08-20 22:08) [7]

А, догнал:


TTestClass(pA^).FThird := 1;
PInt64Array(pB)^[2] := 2;
PIntegerArray(pC^)^[2] := 3;
PString(pD)^[3] := Char(4);


 
Rouse_ ©   (2015-08-20 22:10) [8]


> Pavia ©   (20.08.15 21:47) [4]
> А что надо сделать?
> И честно не понимаю как. Т.е. какие выражения можно использовать
> и какие операции?

Так как мы все программисты, то мы понимаем как данные располагаются в памяти.
Осталось только вспомнить пару нюансов.


> DayGaykin ©   (20.08.15 21:55) [5]

Молодец, почти попал, подумай.


 
Pavia ©   (2015-08-20 22:13) [9]

Я бы вместо

     pA := @A;
     pB := @B;
     pC := @C;
     pD := @D;


Написал бы так.

     pA := @A[0];
     pB := @B[0];
     pC := @C[0];
     pD := @D[0];

Просто динамические массивы во FreePascal и Delphi имеют разную структуру. А так не нужно разбирать их заголовок.


 
Rouse_ ©   (2015-08-20 22:15) [10]


> Pavia ©   (20.08.15 22:13) [9]

Напиши :)


 
DayGaykin ©   (2015-08-20 22:15) [11]


> Просто динамические массивы во FreePascal и Delphi имеют
> разную структуру

Полагаю, в реальной жизни это никогда не потребуется.


 
Игорь Шевченко ©   (2015-08-20 22:20) [12]

Rouse_ ©   (20.08.15 21:33) [3]


> А зачем вообще нужны задачи?


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


 
Pavia ©   (2015-08-20 22:51) [13]

Вот в Delphi 7 работает.

type
 PAInteger=^TAInteger;
 TAInteger=array [0..65535] of Integer;

 PAInt64=^TAInt64;
 TAInt64=array [0..65535] of Int64;
...
     pA := @A;
     pB := @B;
     pC := @C;
     pD := @D;

     TTestClass(pA^).FThird:=1;
     PAInt64(pB)[2]:=2;
     PAInteger(pC^)[2]:=3;
     PByte(@PString(pD)^[3])^:=4;


 
Pavia ©   (2015-08-20 22:58) [14]

А вот если вначале добавить ключик {$H-}, то код ломается.

Интересно, а сразу для всех 4 типов строк такое сделать можно?


 
Игорь Шевченко ©   (2015-08-20 23:19) [15]

Но тем не менее, я сделал :)


 
Rouse_ ©   (2015-08-21 10:25) [16]


> Pavia ©   (20.08.15 22:58) [14]
> А вот если вначале добавить ключик {$H-}, то код ломается.
>
>
> Интересно, а сразу для всех 4 типов строк такое сделать
> можно?

Нет конечно, для каждой свой подход, в этом и фишка :)


 
SergP ©   (2015-08-21 12:02) [17]

2 Rouse_

"используя только указатели", это типа так?

// для pa я хз
pint64(integer(pb)+2*sizeof(Int64))^:=2;
pinteger(pinteger(pc)^+2*sizeof(integer))^:=3;
pchar(pinteger(pd)^+2*sizeof(Char))^:="4";


 
SergP ©   (2015-08-21 12:12) [18]


>  4. D[3] должно равнятся четырем


четырем - это в смысле 4 или "4" ?


 
Rouse_ ©   (2015-08-21 12:18) [19]


> SergP ©   (21.08.15 12:02) [17]
> 2 Rouse_
>
> "используя только указатели", это типа так?

Можно и так. Вот несколько вариантов:

     pA := Pointer(pA^);
     pA := PByte(pA) + SizeOf(Pointer) + 8;
     PInteger(pA)^ := 1;

     pB := PByte(pB) + 16;
     PInteger(pB)^ := 2;

     pC := Pointer(pC^);
     pC := PByte(pC) + 8;
     PInteger(pC)^ := 3;

     pD := Pointer(pD^);
     pD := PByte(pD) + 4;
     PInteger(pD)^ := 4;


     PInteger(NativeInt(pA^) + 2 * SizeOf(Integer) + SizeOf(Pointer))^ := 1;
     PInt64(NativeInt(pB) + 2 * SizeOf(Int64))^ := 2;
     PInteger(NativeInt(pC^) + 2 * SizeOf(Integer))^ := 3;
     PChar(NativeInt(pD^) + 2 * SizeOf(Char))^ := #4;


 
Игорь Шевченко ©   (2015-08-21 12:19) [20]

Как-то так. Хотя, повторюсь, задача неинтересная

    PIntegerArray(pA^)^[3] := 1;
    PByteArray(pB)^[2*SizeOf(Int64)] := 2;
    PIntegerArray(pC^)^[2] := 3;
    (PString(pD))^[3] := Char(4);


 
Rouse_ ©   (2015-08-21 12:21) [21]

ЗЫ: резюмируя
вариант от Pavia ©   (20.08.15 22:51) [13] работает правильно, учитывая 32 и 64 бита.
а вариант от SergP ©   (21.08.15 12:02) [17] работает только на 32 битах.


 
Rouse_ ©   (2015-08-21 12:22) [22]

ЗЗЫ: у ИШ ошибка в 1 при 64 битах, не такая уж и не интересная задача :)


 
Игорь Шевченко ©   (2015-08-21 12:33) [23]

Rouse_ ©   (21.08.15 12:22) [22]

Да, согласен, но ты уже привел пример, так что исправлять нет смысла.
И все-таки я не понимаю, зачем она нужна, эта задача. За подобные извращения надо сразу поражать в правах.


 
Rouse_ ©   (2015-08-21 12:39) [24]

:)
Ну почему сразу поражать, просто проверка как человек работает с указателями и как понимает как данные размещаются в памяти, иногда может и пригодится (к примеру у меня прямая работа с данными в памяти в паре мест где нужна была высокая скорость, встречается)


 
Игорь Шевченко ©   (2015-08-21 13:01) [25]

Rouse_ ©   (21.08.15 12:39) [24]

Поражать за то, что код непонятен.


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


Вот у Саши Шарахова, тут присутствующего, прямая работа тоже встречается, даже в SysUtils включена. Однако, без подобных извратов.


 
Rouse_ ©   (2015-08-21 13:26) [26]

ну если человек не знает как данные размещены в памяти то ему даже код от Sha не поможет :)


 
DayGaykin ©   (2015-08-21 14:02) [27]

Я, например, не знаю как поля экземпляров класса в памяти размещаются и где располагается заголовок динамического массива. Это совершенно не мешает мне трудиться.


 
DayGaykin ©   (2015-08-21 14:06) [28]

Более того, это никак не отражает моего понимания того как работают указатели.


 
NoUser ©   (2015-08-21 16:32) [29]

> Rouse_ ©   (20.08.15 21:22) [0] +
Можно было еще и динамический n-мерный массив  добавить,
и указать в условии, что присвоение должно быть выполнено с помощью Move.
Ну и на выравнивание полей в записи что-то придумать.


> Pavia ©   (20.08.15 22:13) [9]
> Просто динамические массивы во FreePascal и Delphi имеют разную структуру.

А поподробнее ?, так как иногда возникает желание переехать на FreePascal.


 
DayGaykin ©   (2015-08-21 16:43) [30]


> так как иногда возникает желание переехать на FreePascal.

IDE у фрипаскаля еще хуже чем у Delphi. Плохая идея.


 
Rouse_ ©   (2015-08-21 16:56) [31]


> NoUser ©   (21.08.15 16:32) [29]
> > Rouse_ ©   (20.08.15 21:22) [0] +
> Можно было еще и динамический n-мерный массив  добавить,

Можно, но имх и этого достаточно. Вариантов то можно много так наплодить :)


 
Rouse_ ©   (2015-08-21 16:57) [32]


> DayGaykin ©   (21.08.15 14:02) [27]
> Я, например, не знаю как поля экземпляров класса в памяти
> размещаются и где располагается заголовок динамического
> массива. Это совершенно не мешает мне трудиться.

Естетсвенно, большинству это и не нужно, мне же при написании кода защиты приходится много чего желать, в том числе и шифровать данные созданных классов в нужных местах, поэтому все зависит от поставленных задач.


 
Игорь Шевченко ©   (2015-08-21 17:00) [33]


> поэтому все зависит от поставленных задач.


Когда под рукой нет ничего, кроме молотка...


 
Rouse_ ©   (2015-08-21 17:09) [34]


> Игорь Шевченко ©   (21.08.15 17:00) [33]
> Когда под рукой нет ничего, кроме молотка...

Спорно.


 
Игорь Шевченко ©   (2015-08-21 17:58) [35]

Rouse_ ©   (21.08.15 17:09) [34]


> мне же при написании кода защиты приходится много чего желать,
>  в том числе и шифровать данные созданных классов в нужных
> местах


Это же не моя фраза. Но даже данные созданных классов можно шифровать без извращений, если классы спроектированы корректно. Delphi, например, умеет сохранять данные созданных классов в dfm, в этот же механизм вполне можно встроить все, что угодно, в том числе и шифрование


 
Rouse_ ©   (2015-08-21 18:50) [36]


> Игорь Шевченко ©   (21.08.15 17:58) [35]
> Это же не моя фраза. Но даже данные созданных классов можно
> шифровать без извращений, если классы спроектированы корректно.
>  Delphi, например, умеет сохранять данные созданных классов
> в dfm, в этот же механизм вполне можно встроить все, что
> угодно, в том числе и шифрование

Классно рассказал - в теории оно наверное так и выглядит :)
Нет, Игорь, все гораздо проще и сложнее.
Взламывать твое приложение будут не в DFM а правкой памяти запущенного экземпляра приложения. Это же открытая книга - правь что хочешь (вопрос как от этого защититься).
А сам этот тест один из моих стандартных, которые проходили люди при приеме к нам в коллектив на вакансию разработчика VM под 64 бита.
Видишь как все просто иногда бывает :)


 
Игорь Шевченко ©   (2015-08-21 19:04) [37]

Rouse_ ©   (21.08.15 18:50) [36]

>  разработчика VM под 64 бита


Это что ?


> Взламывать твое приложение будут не в DFM а правкой памяти
> запущенного экземпляра приложения. Это же открытая книга
> - правь что хочешь (вопрос как от этого защититься).


Да, я понимаю, что у тебя все вопросы так или иначе связаны с взломом, тут мы в разных сферах совсем.


 
Masterucs ©   (2015-08-21 19:15) [38]

Rouse_, неужели таки нашли тебе помощника?! )


 
Sha ©   (2015-08-21 19:31) [39]

> Rouse_ ©   (21.08.15 18:50) [36]
> А сам этот тест один из моих стандартных...

Кстати, Саш, мысль мелькнула после задачи про тип DayTime.
Можно добавить еще один уровень виртуализации при хранении чисел.
Представлять в системе с переменным основанием и хранить как integer ли int64.
Можно и арифметику свою сделать)


 
Rouse_ ©   (2015-08-21 19:39) [40]


> Игорь Шевченко ©   (21.08.15 19:04) [37]
> Это что ?

Разработка виртуальной машины под 64 бита.


> Masterucs ©   (21.08.15 19:15) [38]
> Rouse_, неужели таки нашли тебе помощника?! )

Нет, не получилось, не смогли найти человека с устраивающей меня квалификацией.
Поэтому вакансия открыта.


> Sha ©   (21.08.15 19:31) [39]
> Можно добавить еще один уровень виртуализации при хранении
> чисел.
> Представлять в системе с переменным основанием и хранить
> как integer ли int64.
> Можно и арифметику свою сделать)

У меня в виртуалке троичная система счисления используется, кстати по твоей подсказке, ну и плюс шифрование :)


 
DayGaykin ©   (2015-08-21 22:39) [41]

А как код для этой VM создается?


 
Rouse_ ©   (2015-08-22 01:01) [42]

Декомпилируем машкод, строим графы, анализируем векторы графов для рассчета порога виртуализации (грубо чтобы незначащий инкремент в цикле не отнимал 90 процентов в пикода на развертке цикла, к примеру), генерируем машкод с заглушками на местах оффсетоф, потом обфусцируем в несколько проходов, результат идет на компилер ВМ.
Финальная машина не сильно принципиальна, я обычно стековый стакан использую на стрелке Пирса, но при должном опыте даже на брейнфак можно заточить


 
Германн ©   (2015-08-22 01:08) [43]


> DayGaykin ©   (21.08.15 22:39) [41]
>
> А как код для этой VM создается?


 
Германн ©   (2015-08-22 01:10) [44]


> Rouse_ ©   (22.08.15 01:01) [42]
>
> Декомпилируем машкод, строим графы, анализируем векторы
> графов для рассчета порога виртуализации (грубо чтобы незначащий
> инкремент в цикле не отнимал 90 процентов в пикода на развертке
> цикла, к примеру), генерируем машкод с заглушками на местах
> оффсетоф, потом обфусцируем в несколько проходов, результат
> идет на компилер ВМ.
> Финальная машина не сильно принципиальна, я обычно стековый
> стакан использую на стрелке Пирса, но при должном опыте
> даже на брейнфак можно заточить

Это просто шедевр!
:)


 
Inovet ©   (2015-08-22 01:31) [45]

Статья у тебя была на эту тему. Помнится, я тогда опознал Брейнфак, хотя, был бы другой, может быть, и другой бы за него принял.:)


 
Rouse_ ©   (2015-08-22 02:22) [46]

Ты видимо про нее: http://habrahabr.ru/post/218887/
Правда, это статья про взлом, а не про защиту :)


 
Inovet ©   (2015-08-22 02:39) [47]

> [46] Rouse_ ©   (22.08.15 02:22)

Дык, две стороны одного процесса.


 
Pavia ©   (2015-08-22 11:16) [48]

Удалено модератором


 
Rouse_ ©   (2015-08-22 11:18) [49]

Удалено модератором


 
Rouse_ ©   (2015-08-22 12:08) [50]

Удалено модератором


 
Rouse_ ©   (2015-08-22 12:20) [51]

Удалено модератором


 
Rouse_ ©   (2015-08-22 12:24) [52]

Перенес новую задачку в новую ветку, дабы не потерялась :)


 
Pavia ©   (2015-08-22 12:31) [53]

Удалено модератором


 
Rouse_ ©   (2015-08-22 12:36) [54]


> Pavia ©   (22.08.15 12:31) [53]

Да, помню, но появились новые люди, поэтому твой пост со ссылкой на решение убил, думаю новичкам будет интересно :)



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

Форум: "Прочее";
Текущий архив: 2016.05.08;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.6 MB
Время: 0.002 c
15-1440094960
Rouse_
2015-08-20 21:22
2016.05.08
Пятничная головоломка от Розыча


15-1440264646
Pavia
2015-08-22 20:30
2016.05.08
Линкер и редактор объектников


15-1440322751
megavoid
2015-08-23 12:39
2016.05.08
Нужна ли грамотность в работе программиста?


2-1411153202
ser
2014-09-19 23:00
2016.05.08
запись в ini файл


15-1436333807
Ega23
2015-07-08 08:36
2016.05.08
Почему Москва - порт пяти морей?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский