[Ответить в тред] Ответить в тред

03/04/16 - Набор в модераторы 03.04 по 8.04
26/03/16 - Конкурс: Помоги гомункулу обрести семью!
15/10/15 - Набор в модераторы 15.10 по 17.10


[Назад][Обновить тред][Вниз][Каталог] [ Автообновление ] 4 | 1 | 4
Назад Вниз Каталог Обновить

Рекомендация по программированию С/С++ el_programmer (Microsoft Windows 7: Chromium based) 10/05/16 Втр 17:04:14  1701968  
14628890544640.png (8Кб, 456x136)
14628890544641.png (147Кб, 580x558)
14628890544652.png (2Кб, 472x33)
Посмотрите пример кода рис. 1



Разъяснение

Указатель хотят сдвинуть на определённое количество байт. Этот код будет корректно работать в Win32 программе, так как в ней размер указателя совпадает с размером типа long. Однако, если мы скомпилируем 64-битный вариант программы, то указатель станет 64-битным, и при преобразовании его в тип long, будут потеряны значения старших битов.

Примечание. В Linux используется другая модель данных. В 64-битных Linux программах тип 'long' является 64-битным, однако, всё равно плохая идея - использовать 'long' для хранения указателя. Во-первых, такой код нередко попадает в Windows приложения, где является некорректным. Во-вторых, существуют специальные типы, само название которых подразумевает, что в них может храниться указатель. Например, это intptr_t. Использование таких типов облегчает понимание программы при её изучении.

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

Наглядно этот ошибку можно проиллюстрировать следующим образом (рис. 2)

Иногда такие ошибки бывает очень трудно заметить. Программа "почти работает". Ошибки потери старших битов в указателях могут проявляться только через несколько часов активной работы с программой. Сначала память выделяется в младших адресах памяти, поэтому все объекты и массивы лежат в младших 4 гигабайтах памяти. Всё работает хорошо.

В процессе работы приложения память фрагментируется, и даже если программа использует не очень много памяти, новые объекты могут быть созданы за пределами первых 4 гигабайт памяти. Вот здесь и начинаются проблемы; специально повторить возникающие проблемы очень трудно.






Корректный код

Для целочисленного представления указателей можно использовать такие типы как size_t, INT_PTR, DWORD_PTR, intrptr_t, uintptr_t и так далее.

Рис. 3

На самом деле, здесь вообще можно было обойтись без явных приведений типов. Нигде не упоминается, что выравнивание отлично от стандартного, т.е. нет никакой магии с использованием __declspec(align( # )) и тому подобного. Значит, указатели сдвигаются на количество байт, кратное размеру Ipp32f; в противном случае, здесь возникнет неопределённое поведение (см. EXP36-C).

Поэтому можно написать так:

img += iStep / sizeof(*img);





Рекомендация

Используйте специальные типы для хранения указателей. Никаких int или long. Наиболее универсальным решением являются следующие типы: intptr_t, uintptr_t. В Visual C++ доступны также следующие типы: INT_PTR, UINT_PTR, LONG_PTR, ULONG_PTR, DWORD_PTR. Само название типа говорит, что в него может быть помещён указатель.

Указатель вполне можно поместить в типы size_t, ptrdiff_t, но рекомендовать это, пожалуй, не стоит. У этих типов другой смысл - они предназначены для хранения размеров и индексов.

В uintptr_t нельзя поместить указатель на функцию-член класса. Функции-члены классов несколько отличаются от стандартных функций. Кроме самого указателя, они хранят скрытое значение this, который указывает на объект класса. Впрочем, это не важно - в 32-битной программе вы не можете положить такой указатель в unsigned int. Такие указатели всегда обрабатываются особым образом, поэтому и проблем с ними в 64-битных программах не возникает. По крайней мере, я таких ошибок не видел.

Если вы собираетесь сделать свою программу 64-битной, в первую очередь следует просмотреть и изменить все фрагменты кода, где указатели преобразовываются в 32-битные целочисленные типы данных. Напомню - в программе будут и другие проблемные места, но начать стоит именно с указателей.


См. другие рекомендации тут: http://www.viva64.com/ru/b/0391/ или ПДФ на английском: https://yadi.sk/i/zKHIOS84r87nk
Аноним (Microsoft Windows Phone: Internet Explorer) 13/05/16 Птн 04:41:55  1705030
>>1701968 (OP)
>разная разрядность указателей на 32 и 64 битных системах.
Спасибо, капитан. Даже и не знаю что бы мы делали без тебя. Алсо ты забыл добавить что можно использовать смартпоинтеры и не ебать себе мозг. А может и не забыл - мне в лом было это читать.
Аноним (Microsoft Windows 10: Chromium based) 13/05/16 Птн 08:16:00  1705059
>>1701968 (OP)
>2016
>байтоеб
>да еще и крестоблядь
>и даже не может найти правильный раздел для своих байтопроблем
Качественно посрал на макушку ОПа-долбоеба.
Аноним (Linux: Chromium based) 14/05/16 Суб 00:49:02  1706103
>>1705059
Это кто вскукарекнул, веб-макака? Не могу разобрать по кудахтанью.
Аноним (Linux: Firefox based) 14/05/16 Суб 04:04:53  1706243
https://2ch.hk/habr/

[Назад][Обновить тред][Вверх][Каталог] [Реквест разбана] [Подписаться на тред] [ ] 4 | 1 | 4
Назад Вверх Каталог Обновить

Топ тредов