Новый метод IntPtr.Add - мне не хватает точки int? - PullRequest
2 голосов
/ 24 ноября 2010

Начиная с FW 4.0, структура IntPtr имеет метод Add:

public static IntPtr Add(
    IntPtr pointer,
    int offset
)

Это здорово, так как предполагается, что мы ответим на все те вопросы по IntPtr математике, которые у нас были ( 1 , 2 , возможно, еще).

Но почему offset int?
Разве это не должно быть IntPtr? Я легко могу себе представить смещение 64-битного указателя на значение, которое выходит за пределы int.


Например, рассмотрим Marshal.OffsetOf:

public static IntPtr OffsetOf(
    Type t,
    string fieldName
)

Возвращает IntPtr в качестве смещения для элемента структуры. Что имеет смысл! И вы не можете легко использовать это смещение с новым методом Add. Вам придется привести его к Int64, а затем несколько раз вызвать Add в цикле.

Кроме того, кажется, что убивает сама идея, что IntPtr.Size не имеет отношения к правильно написанному приложению. Вам нужно будет привести смещение к определенному типу, например Int64, после чего вы должны начать управлять разницей в размерах. И представьте, что произойдет, когда появится 128-битный IntPtr.


Мой вопрос здесь, почему?
Я прав в своих выводах, или я упускаю суть?

Ответы [ 2 ]

5 голосов
/ 24 ноября 2010

Это соответствует ограничению в архитектуре x64. Относительная адресация ограничена знаковым 32-битным значением смещения. Мэтт Петрек упоминает об этом в этой статье (рядом с «К счастью, ответ - нет»). Это ограничение также объясняет, почему .NET-объекты по-прежнему ограничены 2 ГБ в 64-битном режиме. Точно так же в родном x64 C / C ++ выделение памяти кода также ограничено. Дело не в том, что это невозможно, смещение может быть сохранено в 64-битном регистре, просто это сделает индексирование массива на лот дороже.

Таинственный тип возвращаемого значения Marshal.OffsetOf (), вероятно, является угловым случаем. Управляемая структура может привести к неуправляемой версии после применения [StructLayout] и [MarshalAs], размер которых превышает 2 ГБ.

Да, это не будет соответствовать будущей 128-битной архитектуре. Но чрезвычайно сложно подготовить современное программное обеспечение для арки, когда никто не знает, как оно будет выглядеть. Возможно, старая пословица подходит, 16 Терабайт должно быть достаточно для всех. И есть еще много места для роста, 2 ^ 64 довольно большое число. Текущие 64-битные процессоры реализуют только 2 ^ 48. Некоторые серьезные нетривиальные проблемы должны быть решены до того, как машины подойдут так близко.

1 голос
/ 24 ноября 2010

Если вы определите только:

public static IntPtr Add(IntPtr pointer, IntPtr offset)

затем, добавление 32-битного смещения к 64-битному указателю менее читабельно, ИМХО.

Опять же, если вы определите

public static IntPtr Add(IntPtr pointer, long offset)

тогда, добавление 64-битного смещения к 32-битному указателю также плохо.

Кстати, Substract возвращает IntPtr, поэтому логика IntPtr в любом случае не нарушается.

...