Потеряется ли указатель?
От: SanyaVB  
Дата: 02.07.14 06:24
Оценка:
Встретил такой код:
public unsafe static float* GetVectorsPointer(this Vector[] vectorArray)
{
    fixed (Vector* vectors = vectorArray)
        return (float*)vectors;
}


Может получится так что полученный float* уже не ссылается на массив векторов? Скажем после работы мусоросборщика...
Re: Потеряется ли указатель?
От: Jack128  
Дата: 02.07.14 06:45
Оценка: +1
Здравствуйте, SanyaVB, Вы писали:

SVB>Встретил такой код:

SVB>
SVB>public unsafe static float* GetVectorsPointer(this Vector[] vectorArray)
SVB>{
SVB>    fixed (Vector* vectors = vectorArray)
SVB>        return (float*)vectors;
SVB>}
SVB>


SVB>Может получится так что полученный float* уже не ссылается на массив векторов? Скажем после работы мусоросборщика...

естественно может быть. вектор должен быть за'fix'рован все то время, пока ты оперируешь указателем.
Re[2]: Потеряется ли указатель?
От: SanyaVB  
Дата: 02.07.14 07:13
Оценка:
Здравствуйте, Jack128, Вы писали:

J>Здравствуйте, SanyaVB, Вы писали:


SVB>>Встретил такой код:

SVB>>
SVB>>public unsafe static float* GetVectorsPointer(this Vector[] vectorArray)
SVB>>{
SVB>>    fixed (Vector* vectors = vectorArray)
SVB>>        return (float*)vectors;
SVB>>}
SVB>>


SVB>>Может получится так что полученный float* уже не ссылается на массив векторов? Скажем после работы мусоросборщика...

J>естественно может быть. вектор должен быть за'fix'рован все то время, пока ты оперируешь указателем.

Ко мне тоже эта мысль пришла. Но заставляет задуматься следующие два примера:



        private unsafe void Example1()
        {
            fixed (float* pointer = vectors.GetVectorsPointer()) //Error: You cannot use the fixed statement to take the address of an already fixed expression
            {
                 //тут что то дальше делаем
            }
        }


        private unsafe void Example2()
        {
            float* pointer = vectors.GetVectorsPointer(); // pointer уже зафиксирована

             //тут что то дальше делаем
        }


Походу Example2() не потеряет указатель на массив векторов.
Потеря может произойти только в том случае если мы в локальную переменную IntPtr загоним new IntPtr(pointer); А потом где то из кода будем по этому адресу ссылаться
Re[3]: Потеряется ли указатель?
От: Jack128  
Дата: 02.07.14 07:41
Оценка: +1
Здравствуйте, SanyaVB, Вы писали:

SVB>Ко мне тоже эта мысль пришла. Но заставляет задуматься следующие два примера:



SVB>[c#]


SVB> private unsafe void Example1()

SVB> {
SVB> fixed (float* pointer = vectors.GetVectorsPointer()) //Error: You cannot use the fixed statement to take the address of an already fixed expression
SVB> {
SVB> //тут что то дальше делаем
SVB> }
SVB> }

зафиксирован не vectors, а результат выражения vectors.GetVectorsPointer(). тоже самое будет есть ты попытаешься например int зафиксировать.
Re[4]: Потеряется ли указатель?
От: SanyaVB  
Дата: 02.07.14 07:49
Оценка:
Здравствуйте, Jack128, Вы писали:

J>Здравствуйте, SanyaVB, Вы писали:


SVB>>Ко мне тоже эта мысль пришла. Но заставляет задуматься следующие два примера:


J>зафиксирован не vectors, а результат выражения vectors.GetVectorsPointer(). тоже самое будет есть ты попытаешься например int зафиксировать.

Вы имеете виду что зафиксируется указатель,а не данные на которые указывает указатель?
Re[5]: Потеряется ли указатель?
От: Jack128  
Дата: 02.07.14 07:57
Оценка:
Здравствуйте, SanyaVB, Вы писали:

J>>зафиксирован не vectors, а результат выражения vectors.GetVectorsPointer(). тоже самое будет есть ты попытаешься например int зафиксировать.

SVB>Вы имеете виду что зафиксируется указатель,а не данные на которые указывает указатель?

Именно.
Re: Потеряется ли указатель?
От: nikov США http://www.linkedin.com/in/nikov
Дата: 02.07.14 16:05
Оценка:
Здравствуйте, SanyaVB, Вы писали:

SVB>Встретил такой код:

SVB>
SVB>public unsafe static float* GetVectorsPointer(this Vector[] vectorArray)
SVB>{
SVB>    fixed (Vector* vectors = vectorArray)
SVB>        return (float*)vectors;
SVB>}
SVB>


SVB>Может получится так что полученный float* уже не ссылается на массив векторов? Скажем после работы мусоросборщика...


Конечно, может. Подход, использованный здесь в C# и CLR называется декларативная фиксация (declarative pinning). Сигнатура локальной переменной, указанная в метаданных, помимо типа переменной, может содержать модификатор pinned. Когда включается сборщик мусора, то он знает, что все активные локальные переменные на стеке являются рутами графа живых объектов (которые нельзя собирать, но, потенциально, можно перемещать с целью дефрагментации кучи), а активные локальные переменные с модификатором pinned вдобавок требуют, чтобы объекты, на которые они ссылаются, не перемещались в памяти. Таким образом, зафиксированность — это не признак, хранящийся в самом объекте, или в ссылке на объект (который сохранялся при копировании этой ссылки между переменными), а состояние объекта, существующее в силу того, что хотя бы одна ссылка на него находится в руте GC, помеченном модификатором pinned (причём этот модификатор может присутствовать только у локальных переменных). Как только соответствующая переменная перестаёт быть активной (напрмер, мы выходим из метода или из fixed блока*), то объект перестаёт быть зафиксированным (при условии, что это была последняя pinned ссылка на него).

Вместо декларативного подхода можно императивно вызвать метод GCHandle.Alloc, который проинструктирует GC, что данный объект нельзя перемещать, и потом вручную отменить его (возможно, в совершенно другом методе). GC будет хранить соответствующую информацию в своих внутренних таблицах:

GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned); // fix
// ...

handle.Free(); // unfix



* IL не хранит информацию о границах блоков, и GC может считать переменную неактивной, если может доказать (на основе информации, предоставленной JIT-компилятором), что после настоящего момента код данного метода уже не обращается к данной локальной переменной (даже если с точки зрения C# она ещё in scope). Но для fixed statement компилятор C# искусственно всавляет IL инструкции, которые будут поддерживать объявленную там локальную переменную активной до конца блока, несмотря на ухищрения JIT и GC.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.