Хотите знать, почему арифметика указателя не работает в asp.net - PullRequest
2 голосов
/ 07 июля 2011

Я хотел попробовать арифметику указателей в c #. Я использовал веб-приложение asp.net, ожидая, что это не будет иметь значения, будь то это или консольное приложение.

вот что я попробовал:

public class memorytest
{
    public class Sample
    {
        public int A;
        public int B;
        public int C;
        public int D;
    }

   public static unsafe void Main()
   {
    Sample s = new Sample {A = 1, B = 2, C = 3, D = 4};
    int a = 1;
    int b = 2;
    int* pA = &a;
    int* pB = &b;
    Debug.WriteLine("{0:x16}",* pB);
    Debug.WriteLine("{0:x16}",*(pB - 1));
    Debug.WriteLine(*pA);
    Debug.WriteLine("{0:x16}",*(pB - 2));
    }

}

Результат был таким:

0000000000000002, 0000000004b5ca00, 1, 0000000004b5c9fc

Я, очевидно, ожидал, что второй будет число 1. Кто-нибудь это понимает?

Ответы [ 5 ]

10 голосов
/ 08 июля 2011

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

Предполагая, что по какой-то причине вы хотите продолжать писать программы для проверки их собственного состояния стека: вы перестали экспериментировать слишком рано.Программа, которую вы должны были написать:

Debug.WriteLine("{0:x16}",*(pB - 1));
Debug.WriteLine("{0:x16}",*(pB + 0));    
Debug.WriteLine("{0:x16}",*(pB + 1));

, и тогда вы получили бы вывод

00000badf00dd00d  <-- some pointer value
0000000000000002  <-- contents of b
0000000000000001  <-- contents of a

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

Конечно, как уже указывали другие, мы не даем никаких гарантий относительно того, как вещи размещаются в стеке,или даже если вещи попадают в стек в первую очередь;локальные переменные могут быть помещены в кучу в некоторых ситуациях, и локальные переменные, адреса которых никогда не берутся, могут быть зарегистрированы.Например, что произойдет, если вы не берете адрес «а»?Это все еще заканчивается в стеке?Возможно, нет!

6 голосов
/ 07 июля 2011

Эта проблема не связана с ASP.net.Ваше использование арифметики с указателями просто неправильно.

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

Aнесколько сложностей в хранении логических локальных переменных:

  • Большинство компиляторов помещают локальные переменные в регистр, если вы не получите их адрес.
  • переменные, связанные лямбда-выражением, или переменные вasync метод используется для объектов кучи.
  • Даже если они действительно находятся в стеке, порядок произвольный.
  • Между логическими переменными и ячейками памяти нет даже соответствия 1: 1.Ячейка памяти может быть повторно использована, когда переменная выходит из области видимости.

Арифметика указателей обычно может использоваться только в пределах одного выделенного блока памяти.

Таким образом, результат *(pB - 1)что разыменовывает память перед b - неопределенное поведение.

В .net вы обычно можете использовать арифметику указателей внутри массивов или выделенных вручную блоков памяти.

4 голосов
/ 07 июля 2011

Ваша вторая ссылка разыменовывает адрес pB - 1, а не разыменовывает pB и вычитает 1.

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

Debug.WriteLine("{0:x16}",*(pB) - 1);
1 голос
/ 07 июля 2011

Я не думаю, что вы можете или должны делать какие-либо предположения о том, ГДЕ в памяти .NET помещает ваши переменные.В вашем случае *pB правильно разрешается до 2, поскольку это значение b.Я не думаю, что вы можете предположить, что a будет выделено «до» b, так что *(pB - 1) указывает на это.Вы видите целое значение «что бы ни было int перед b в стеке».

0 голосов
/ 07 июля 2011

Когда вы пишете:

Debug.WriteLine("{0:x16}",*(pB - 1)); 

Вы берете значение ячейки памяти pB - 1. Не значение pB минус один.

Попробуйте использовать это:

Debug.WriteLine("{0:x16}",(*(pB) - 1)); 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...