64-битный сферичекий конь.
От: _Winnie Россия C++.freerun
Дата: 18.10.04 10:14
Оценка:
Предположим, есть код. Древний. Работающий. На 32-битном компиляторе.

void f(X *array, unsigned i) { работаем с array[i]; }
...
X buf[100];
f(array+20, -10)



Как будет работать этот код на компиляторе с 64-битными указателями и 32-битным int ?

Любопытсво чисто праздное, просто интересно.
Правильно работающая программа — просто частный случай Undefined Behavior
Re: 64-битный сферичекий конь.
От: _Winnie Россия C++.freerun
Дата: 18.10.04 10:18
Оценка:
Здравствуйте, _Winnie, Вы писали:

Опечатался

_W>
_W>X buf[100];
_W>f(buf+20, -10)
_W>
Правильно работающая программа — просто частный случай Undefined Behavior
Re: 64-битный сферичекий конь.
От: elcste  
Дата: 18.10.04 11:01
Оценка:
Здравствуйте, _Winnie, Вы писали:

_W>void f(X *array, unsigned i) { работаем с array[i]; }
_W>...
_W>X buf[100];
_W>f(array+20, -10)

_W>Как будет работать этот код на компиляторе с 64-битными указателями и 32-битным int ?

Это undefined behavior, разумеется. Как оно будет проявляться в Вашей гипотетической реализации, предсказать нельзя. Никто ведь не знает, как этот 64-разрядный указатель устроен. Возможно, в нем 32 разряда – селектор, а 32 – смещение внутри сегмента; только над последним и выполняется адресная арифметика. Тогда Вы опять никаких внешних проявлений неопределенного поведения не увидите.
Re: 64-битный сферичекий конь.
От: achp  
Дата: 18.10.04 11:46
Оценка:
Здравствуйте, _Winnie, Вы писали:

_W>
_W>void f(X *array, unsigned i) { работаем с array[i]; }
_W>...
_W>X buf[100];
_W>f(array+20, -10)
_W>


_W>Как будет работать этот код на компиляторе с 64-битными указателями и 32-битным int ?


Плохо будет работать. Внутри f имеем преобразование типа i от unsigned к ptrdiff_t. Так как в данном случае ptrdiff_t вообще не является одним из целочисленных типов, описанных в Стандарте языка, то уже только из этого следует "правовая неопределенность" в данном преобразовании. Если же на данное преобразование распространяются положения §4.7(3) Стандарта, то тем более — получим значение типа ptrdiff_t, равное в данном случае ((ptrdiff_t(1) << 32) — 10) (то есть большое положительное число).
Я кончил, джентльмены, мне остается только поблагодарить вас за внимание.
Re[2]: 64-битный сферичекий конь.
От: Tom Россия http://www.RSDN.ru
Дата: 18.10.04 11:59
Оценка:
А где тут UB ?

"elcste" <30120@news.rsdn.ru> wrote in message news:856537@news.rsdn.ru...
> Здравствуйте, _Winnie, Вы писали:
>
>
> _W>void f(X *array, unsigned i) { работаем с array[i]; }
> _W>...
> _W>X buf[100];
> _W>f(array+20, -10)
>

> _W>Как будет работать этот код на компиляторе с 64-битными указателями и 32-битным int ?
>
> Это undefined behavior, разумеется. Как оно будет проявляться в Вашей гипотетической реализации, предсказать нельзя. Никто ведь не знает, как этот 64-разрядный указатель устроен. Возможно, в нем 32 разряда – селектор, а 32 – смещение внутри сегмента; только над последним и выполняется адресная арифметика. Тогда Вы опять никаких внешних проявлений неопределенного поведения не увидите.
Posted via RSDN NNTP Server 1.9 gamma
Народная мудрось
всем все никому ничего(с).
Re[2]: 64-битный сферичекий конь.
От: achp  
Дата: 18.10.04 12:46
Оценка:
A>Плохо будет работать. Внутри f имеем преобразование типа i от unsigned к ptrdiff_t. Так как в данном случае ptrdiff_t вообще не является одним из целочисленных типов, описанных в Стандарте языка, то уже только из этого следует "правовая неопределенность" в данном преобразовании. Если же на данное преобразование распространяются положения §4.7(3) Стандарта, то тем более — получим значение типа ptrdiff_t, равное в данном случае ((ptrdiff_t(1) << 32) — 10) (то есть большое положительное число).

Вообще-то сейчас перечитал 5.7(5), ptrdiff_t там не упоминается (для меня это стало откровением ). Ну что ж, значит к указателю прибавится целочисленное значение типа unsigned, то есть большое положительное число. Ничего в принципе не меняется.
Я кончил, джентльмены, мне остается только поблагодарить вас за внимание.
Re[2]: 64-битный сферичекий конь.
От: MaximE Великобритания  
Дата: 18.10.04 13:47
Оценка:
elcste wrote:

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

>
>
> _W>void f(X *array, unsigned i) { работаем с array[i]; }
> _W>...
> _W>X buf[100];
> _W>f(array+20, -10)
>

> _W>Как будет работать этот код на компиляторе с 64-битными указателями и 32-битным int ?
>
> Это undefined behavior, разумеется. Как оно будет проявляться в Вашей гипотетической реализации, предсказать нельзя. Никто ведь не знает, как этот 64-разрядный указатель устроен. Возможно, в нем 32 разряда – селектор, а 32 – смещение внутри сегмента; только над последним и выполняется адресная арифметика.

Даже если это и будет так, то на адресной арифметике C++ это никак не отразится.

Пример: 32 битный указатель на x86 виндозе и линуксе есть не что иное как 10-bit индекс в каталоге (1024 записи) таблиц страниц + 10-bit индекс в таблице (1024 записи) страниц + 12 бит смещение (0 — 4kb) на странице. И этот указатель представлен в C++ как собственное реальное значение, который мы можем инкрементировать и т.д..

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9 gamma
Re[3]: 64-битный сферичекий конь.
От: Кодт Россия  
Дата: 18.10.04 13:58
Оценка:
Здравствуйте, achp, Вы писали:

A>>Плохо будет работать. Внутри f имеем преобразование типа i от unsigned к ptrdiff_t. Так как в данном случае ptrdiff_t вообще не является одним из целочисленных типов, описанных в Стандарте языка, то уже только из этого следует "правовая неопределенность" в данном преобразовании. Если же на данное преобразование распространяются положения §4.7(3) Стандарта, то тем более — получим значение типа ptrdiff_t, равное в данном случае ((ptrdiff_t(1) << 32) — 10) (то есть большое положительное число).


A>Вообще-то сейчас перечитал 5.7(5), ptrdiff_t там не упоминается (для меня это стало откровением ). Ну что ж, значит к указателю прибавится целочисленное значение типа unsigned, то есть большое положительное число. Ничего в принципе не меняется.


Всё упирается в вопрос: а какой размер у (unsigned) int?

При вызове f(..., -10) мы имеем int -> unsigned int, получаем большое положительное число. Об этом, кстати, должен сообщить компилятор варнингом.

Внутри функции unsigned -> ptrdiff_t.
Если его разрядность меньше (что вряд ли) или равна разрядности int, то получим такое же число со знаком.
Если же больше — то опаньки.

Пример ситуации, где sizeof(ptrdiff_t) > sizeof(int) — на 16-битном x86, модель памяти huge.
Перекуём баги на фичи!
Re[4]: 64-битный сферичекий конь.
От: achp  
Дата: 18.10.04 14:46
Оценка: 20 (1)
Здравствуйте, Кодт, Вы писали:

К>Всё упирается в вопрос: а какой размер у (unsigned) int?


Насколько я понимаю, вопрос задается применительно к платформе IA64.

A>>Вообще-то сейчас перечитал 5.7(5), ptrdiff_t там не упоминается (для меня это стало откровением ). Ну что ж, значит к указателю прибавится целочисленное значение типа unsigned, то есть большое положительное число. Ничего в принципе не меняется.


К>Внутри функции unsigned -> ptrdiff_t.


Я тоже так сначала подумал, но, перечитав 5.7(5), не увидел там упоминания ptrdiff_t. Значит, целое должно рассматриваться в соответствии со своим типом. unsigned(-10) — это большое положительное целое.

Значит, имеем неопределенное поведение.

Кстати, формально неопределенное поведение в приведенном куске кода есть вне зависимости от размеров типов.
Я кончил, джентльмены, мне остается только поблагодарить вас за внимание.
Re: 64-битный сферичекий конь.
От: jazzer Россия Skype: enerjazzer
Дата: 18.10.04 14:53
Оценка:
Здравствуйте, _Winnie, Вы писали:

_W>Предположим, есть код. Древний. Работающий. На 32-битном компиляторе.


_W>
_W>void f(X *array, unsigned i) { работаем с array[i]; }
_W>...
_W>X buf[100];
_W>f(array+20, -10)
_W>



_W>Как будет работать этот код на компиляторе с 64-битными указателями и 32-битным int ?


_W>Любопытсво чисто праздное, просто интересно.


зависит от того, какого размера у тебя array.
если указатель array+20, смещенный на это огромное число (unsigned)-10, все равно будет указывать внутрь array — нет проблем.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: 64-битный сферичекий конь.
От: Кодт Россия  
Дата: 18.10.04 15:10
Оценка:
Здравствуйте, jazzer, Вы писали:

J>зависит от того, какого размера у тебя array.

J>если указатель array+20, смещенный на это огромное число (unsigned)-10, все равно будет указывать внутрь array — нет проблем.

Нифига себе "нет проблем". Получим валидный, но совершенно левый указатель.
void print_nth(int* p, unsigned short o)
{ printf("%d\n", *(p+o)); }

const unsigned long L=1L<<16;
int buf[L+1];

main()
{
  buf[0] = 123;
  buf[L] = 456;
  print_nth(buf+0,-0);
  print_nth(buf+1,-1);
}
Перекуём баги на фичи!
Re[5]: 64-битный сферичекий конь.
От: _Winnie Россия C++.freerun
Дата: 18.10.04 15:36
Оценка:
Здравствуйте, achp, Вы писали:

Вроде стало понятно. Это Undefined Behavior, и в его частный случай — правильная работа на Wintel A32
Спасибо.
Правильно работающая программа — просто частный случай Undefined Behavior
Re: 64-битный сферичекий конь.
От: McSeem2 США http://www.antigrain.com
Дата: 18.10.04 15:44
Оценка:
Здравствуйте, _Winnie, Вы писали:

_W>
_W>void f(X *array, unsigned i) { работаем с array[i]; }
_W>...
_W>X buf[100];
_W>f(array+20, -10)
_W>


_W>Как будет работать этот код на компиляторе с 64-битными указателями и 32-битным int ?

_W>Любопытсво чисто праздное, просто интересно.

А почему именно unsigned? Это принципиально? Насколько я понимаю адресную арифметику, в отрицательных смещениях нет никакого криминала (если не выходит за границы валидной области памяти). Принципиально то, что индекс должен быть знаковым, то есть, int. Для беззнакового по идее должно работать, если только sizeof(ptr) == sizeof(unsigned).

Проверил на Sun в 64-бит режиме, с int работает, с unsigned, как и предполагалось, падает
#include <stdio.h>
int f(const int* array, unsigned i) { return array[i]; }
int main()
{
   int buf[100];
   for(int i = 0; i < 100; i++) buf[i] = i;
   buf[10] = 12345;
   printf("%d\n", f(buf+20, -10));
}


rndusextiger:~>CC -xarch=generic64 a.cpp
rndusextiger:~>./a.out
Segmentation fault (core dumped)
rndusextiger:~>


С int-ом работат нормально. На 32-х битном коде работает и так и так.

rndusextiger:~>CC -xarch=generic a1.cpp
rndusextiger:~>./a.out
12345
rndusextiger:~>
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[3]: 64-битный сферичекий конь.
От: achp  
Дата: 18.10.04 16:16
Оценка: +1 :)
Здравствуйте, Кодт, Вы писали:

К>Нифига себе "нет проблем". Получим валидный, но совершенно левый указатель.


Это как? Он либо "валидный", либо "левый".
Я кончил, джентльмены, мне остается только поблагодарить вас за внимание.
Re[4]: 64-битный сферичекий конь.
От: Кодт Россия  
Дата: 18.10.04 16:27
Оценка:
Здравствуйте, achp, Вы писали:

К>>Нифига себе "нет проблем". Получим валидный, но совершенно левый указатель.


A>Это как? Он либо "валидный", либо "левый".


А вот так:
int xz() { return rand()%100; }
// int xz() { return 50; }

int data[100] = { 0 };
main()
{
  data[50] = 123;
  printf("%d", data[xz()]); // ой! а что это за нолик? а в предыдущей версии работало как надо...
  printf("%d", data[rand()]); // а здесь какое-то странное число получилось... если не AV...
}
Перекуём баги на фичи!
Re[5]: 64-битный сферичекий конь.
От: 0xFADE США github.com/NotImplemented
Дата: 18.10.04 19:08
Оценка:
Здравствуйте, achp, Вы писали:

A>Здравствуйте, Кодт, Вы писали:


К>>Всё упирается в вопрос: а какой размер у (unsigned) int?


A>Насколько я понимаю, вопрос задается применительно к платформе IA64.


A>>>Вообще-то сейчас перечитал 5.7(5), ptrdiff_t там не упоминается (для меня это стало откровением ). Ну что ж, значит к указателю прибавится целочисленное значение типа unsigned, то есть большое положительное число. Ничего в принципе не меняется.


К>>Внутри функции unsigned -> ptrdiff_t.


A>Я тоже так сначала подумал, но, перечитав 5.7(5), не увидел там упоминания ptrdiff_t. Значит, целое должно рассматриваться в соответствии со своим типом. unsigned(-10) — это большое положительное целое.


13.6/13
For every cv-qualified or cv-unqualified object type T there exists candidate operator functions of the form
...
T& operator[](T*, ptrdiff_t);
...

Приведение типа дожлно быть, после чего, по определению, ptr[diff] есть *(ptr + diff).

Определение типа ptrdiff_t зависит от реализации, и, строго говоря, нельзя утверждать, что оно неотрицательно.
Приведенный пример может вполне корректно работать.
Кстати, значение unsigned(-10) тоже implementation defined.

A>Значит, имеем неопределенное поведение.


A>Кстати, формально неопределенное поведение в приведенном куске кода есть вне зависимости от размеров типов.
Re[3]: 64-битный сферичекий конь.
От: jazzer Россия Skype: enerjazzer
Дата: 18.10.04 23:48
Оценка:
Здравствуйте, Кодт, Вы писали:

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


J>>зависит от того, какого размера у тебя array.

J>>если указатель array+20, смещенный на это огромное число (unsigned)-10, все равно будет указывать внутрь array — нет проблем.

К>Нифига себе "нет проблем". Получим валидный, но совершенно левый указатель.

Так не бывает

согласись, что размер массива в 64-битной архитектуре можно сделать больше (unsigned)-10.
И тогда действительно не будет проблем.
Мы же не знаем, какого размера у него массив и как он определяется.

а то, что ты писал про инициализированность элементов массива, согласись, к делу не относится, хотя бы потому, что мы не знаем, как он у него заполняется в реальности.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[3]: 64-битный сферичекий конь.
От: elcste  
Дата: 19.10.04 00:57
Оценка:
Здравствуйте, Tom, Вы писали:

Tom>А где тут UB ?


В вычислении указателя не на элемент массива и не на элемент, следующий за последним элементом массива (6.3.6 в C90, 5.7/5 в C++, 6.5.6/8 в C99).
Re[3]: 64-битный сферичекий конь.
От: elcste  
Дата: 19.10.04 01:06
Оценка:
Здравствуйте, MaximE, Вы писали:

>> Это undefined behavior, разумеется. Как оно будет проявляться в Вашей гипотетической реализации, предсказать нельзя. Никто ведь не знает, как этот 64-разрядный указатель устроен. Возможно, в нем 32 разряда – селектор, а 32 – смещение внутри сегмента; только над последним и выполняется адресная арифметика.


ME>Даже если это и будет так, то на адресной арифметике C++ это никак не отразится.


Честно говоря, не понял, как это соотносится с написанным выше. Разумеется, внутреннее устройство указателя и правила обработки переполнения при адресной арифметике не отразятся на результатах корректных вычислений. Но именно от них будет зависеть наблюдаемый эффект в случае неопределенного поведения.
Re[6]: 64-битный сферичекий конь.
От: elcste  
Дата: 19.10.04 01:26
Оценка: +1
Здравствуйте, 0xFADE, Вы писали:

FAD>13.6/13

FAD>For every cv-qualified or cv-unqualified object type T there exists candidate operator functions of the form
FAD>...
FAD>T& operator[](T*, ptrdiff_t);
FAD>...


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

13.6/1 These candidate functions participate in the operator overload resolution process as described in 13.3.1.2 and are used for no other purpose.


FAD>Приведение типа дожлно быть, после чего, по определению, ptr[diff] есть *(ptr + diff).


Тип ptrdiff_t не имеет никакого отношения к сложению указателя с целым.

FAD>Определение типа ptrdiff_t зависит от реализации, и, строго говоря, нельзя утверждать, что оно неотрицательно.


Что значит "неотрицательно"?.. ptrdiff_t определяется как знаковый целый тип (7.1.6 в C90, 7.17/2 в C99, ср. 5.7/6 в C++).
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.