информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
За кого нас держат?Все любят медСетевые кракеры и правда о деле Левина
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Три миллиона электронных замков... 
 Doom на газонокосилках 
 Умер Никлаус Вирт 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
Ну да. Я просто сказал о наиболее частом использовании. Если... [upd] 03.10.05 13:15  Число просмотров: 2177
Автор: amirul <Serge> Статус: The Elderman
Отредактировано 03.10.05 13:17  Количество правок: 1
<"чистая" ссылка>
> Ну не всегда константный элемент объекта может
> инициализироваться константой. Может это быть и переменная,
> и системный параметр (текущее время, например), и что-то
> считанное из файла.

Ну да. Я просто сказал о наиболее частом использовании. Если оптимизатор не сможет заменить все обращения к константе на ее значение (неизвестное на этапе компиляции), то он просто заведет переменную (вернее он ее заведет в любом случае, но линкер не сможет отрезать "неиспользуемый код"). В случае x86 платформ (что *nix, что винды) никакой readonly памяти не будет. Переменная просто попадет в секцию данных (это если статическая или глобальная) или там же где и все остальные (стек/куча/ручная выделялка), а все попытки обратиться к ней на изменение будут пресекаться на этапе компиляции.

> Мои архаичные копайлеры "mutable" не поймут, ничего,
> смирюсь в ворнингами.

Это ж какой компайлер не понимает стандарта 98-го года? Семь лет прошло как никак - было время привести в соответсвтие так сказать (и это не export, который так до сих пор никем толком и не поддерживается, ибо не совсем понятно как сделать его реализацию)

-----------
Да, кстати, если компилятор таки не понимает стандарта 98-го года, то можно использовать const_cast (из того же стандарта, если он хотя бы частично реализован) ну или c-style cast (обычные скобки) для отрезания константности из типа. Некошерно, зато работать будет и компиляться без ворнингов.
<programming>
[C++] Инициализация константных объектов. 30.09.05 18:08  
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
<"чистая" ссылка>
Многие компиляторы размещают константные переменные в readonly памяти. Интересно, как они поступают с константными объектами, ведь вызывающийся до выполнения основной части программы конструктор должен проинициализировать объект?
И еще. Возмем, скажем "operator+". Обязательно, или полезно, или не стОит, или нельзя описывать аргументы ссылками на константы. Теоретически они меняться не должны, но если имеет место быть ситуация, когда логически объект не меняется, но надо что-то щелкнуть служебное, например счетчик обращений. Какие-нибудь рекомендации есть в этом направлении?
Даже конструктор не всегда вызывается. Один из самых... 03.10.05 11:04  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> Многие компиляторы размещают константные переменные в
> readonly памяти. Интересно, как они поступают с
> константными объектами, ведь вызывающийся до выполнения
> основной части программы конструктор должен
> проинициализировать объект?

Даже конструктор не всегда вызывается. Один из самых распространенных способов использования констант - глобальные (или статические в классе) целочисленные переменные, которые инициализируются прямо на месте. В этом случае оптимизатор заменяет все обращения к константе на ее значение, а линкер вырезает неиспользуемую переменную. Результат - в точности такой же как и при использовании #define, но с типизацией.

> И еще. Возмем, скажем "operator+". Обязательно, или
> полезно, или не стОит, или нельзя описывать аргументы
> ссылками на константы. Теоретически они меняться не должны,

Общая рекомендация при использовании ссылок при передаче параметров: если функция не собирается менять содержимое, ее надо объявлять const. Это не требование языка, а просто стилистическая рекомендация. Таким образом будет видно, если передана неконстантная ссылка, то в нее возвращается какое то значение.

> но если имеет место быть ситуация, когда логически объект
> не меняется, но надо что-то щелкнуть служебное, например
> счетчик обращений. Какие-нибудь рекомендации есть в этом
> направлении?

Ключевое слово mutable придумано специально для таких целей: счетчики ссылок/кеширование и пр. изменения ПРЕДСТАВЛЕНИЯ, которое логически не изменяют сам объект.
Ну не всегда константный элемент объекта может... 03.10.05 11:25  
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
Отредактировано 03.10.05 11:26  Количество правок: 1
<"чистая" ссылка>
> Даже конструктор не всегда вызывается. Один из самых
> распространенных способов использования констант -
> глобальные (или статические в классе) целочисленные
> переменные, которые инициализируются прямо на месте. В этом
> случае оптимизатор заменяет все обращения к константе на ее
> значение, а линкер вырезает неиспользуемую переменную.
> Результат - в точности такой же как и при использовании
> #define, но с типизацией.

Ну не всегда константный элемент объекта может инициализироваться константой. Может это быть и переменная, и системный параметр (текущее время, например), и что-то считанное из файла.

> Общая рекомендация при использовании ссылок при передаче
> параметров: если функция не собирается менять содержимое,
> ее надо объявлять const. Это не требование языка, а просто
> стилистическая рекомендация. Таким образом будет видно,
> если передана неконстантная ссылка, то в нее возвращается
> какое то значение.
>
> Ключевое слово mutable придумано специально для таких
> целей: счетчики ссылок/кеширование и пр. изменения
> ПРЕДСТАВЛЕНИЯ, которое логически не изменяют сам объект.

Мои архаичные копайлеры "mutable" не поймут, ничего, смирюсь в ворнингами.
Ну да. Я просто сказал о наиболее частом использовании. Если... [upd] 03.10.05 13:15  
Автор: amirul <Serge> Статус: The Elderman
Отредактировано 03.10.05 13:17  Количество правок: 1
<"чистая" ссылка>
> Ну не всегда константный элемент объекта может
> инициализироваться константой. Может это быть и переменная,
> и системный параметр (текущее время, например), и что-то
> считанное из файла.

Ну да. Я просто сказал о наиболее частом использовании. Если оптимизатор не сможет заменить все обращения к константе на ее значение (неизвестное на этапе компиляции), то он просто заведет переменную (вернее он ее заведет в любом случае, но линкер не сможет отрезать "неиспользуемый код"). В случае x86 платформ (что *nix, что винды) никакой readonly памяти не будет. Переменная просто попадет в секцию данных (это если статическая или глобальная) или там же где и все остальные (стек/куча/ручная выделялка), а все попытки обратиться к ней на изменение будут пресекаться на этапе компиляции.

> Мои архаичные копайлеры "mutable" не поймут, ничего,
> смирюсь в ворнингами.

Это ж какой компайлер не понимает стандарта 98-го года? Семь лет прошло как никак - было время привести в соответсвтие так сказать (и это не export, который так до сих пор никем толком и не поддерживается, ибо не совсем понятно как сделать его реализацию)

-----------
Да, кстати, если компилятор таки не понимает стандарта 98-го года, то можно использовать const_cast (из того же стандарта, если он хотя бы частично реализован) ну или c-style cast (обычные скобки) для отрезания константности из типа. Некошерно, зато работать будет и компиляться без ворнингов.
*nix константы в readonly памяти держит. 03.10.05 16:49  
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
<"чистая" ссылка>
> Ну да. Я просто сказал о наиболее частом использовании.
> Если оптимизатор не сможет заменить все обращения к
> константе на ее значение (неизвестное на этапе компиляции),
> то он просто заведет переменную (вернее он ее заведет в
> любом случае, но линкер не сможет отрезать "неиспользуемый
> код"). В случае x86 платформ (что *nix, что винды) никакой
> readonly памяти не будет. Переменная просто попадет в
> секцию данных (это если статическая или глобальная) или там
> же где и все остальные (стек/куча/ручная выделялка), а все
> попытки обратиться к ней на изменение будут пресекаться на
> этапе компиляции.

*nix константы в readonly памяти держит.
char *ptr = "core dumped.";
*ptr = 'C';
Эта строка приведет к сегментэйшн фолт.

> Это ж какой компайлер не понимает стандарта 98-го года?

BCC V3.1 от 1992 года и SC V7.2 от 1995 года.
Первый можно кастрировать до необычайно маленьких размеров так чтоб такать с собой буквально на дискетке. Второй правильно работает с памятью.

> Семь лет прошло как никак - было время привести в
> соответсвтие так сказать (и это не export, который так до
> сих пор никем толком и не поддерживается, ибо не совсем
> понятно как сделать его реализацию)

> Да, кстати, если компилятор таки не понимает стандарта
> 98-го года, то можно использовать const_cast (из того же
> стандарта, если он хотя бы частично реализован) ну или
> c-style cast (обычные скобки) для отрезания константности
> из типа. Некошерно, зато работать будет и компиляться без
> ворнингов.

Попробую.
VC в debug режиме тоже 04.10.05 11:47  
Автор: amirul <Serge> Статус: The Elderman
Отредактировано 04.10.05 11:51  Количество правок: 1
<"чистая" ссылка>
> *nix константы в readonly памяти держит.
> char *ptr = "core dumped.";
> *ptr = 'C';
> Эта строка приведет к сегментэйшн фолт.

вот кусок листинга в дебажном режиме
PUBLIC	_main
PUBLIC	??_C@_0N@LCLI@core?5dumped?4?$AA@		; `string'
;	COMDAT ??_C@_0N@LCLI@core?5dumped?4?$AA@
; File d:\work\test\test.c
CONST	SEGMENT
??_C@_0N@LCLI@core?5dumped?4?$AA@ DB 'core dumped.', 00H ; `string'
CONST	ENDS
;	COMDAT _main
_TEXT	SEGMENT
_ptr$ = -4
_main	PROC NEAR					; COMDAT

; 2    : main() {

  00000	55		 push	 ebp
  00001	8b ec		 mov	 ebp, esp
  00003	83 ec 44	 sub	 esp, 68			; 00000044H
  00006	53		 push	 ebx
  00007	56		 push	 esi
  00008	57		 push	 edi
  00009	8d 7d bc	 lea	 edi, DWORD PTR [ebp-68]
  0000c	b9 11 00 00 00	 mov	 ecx, 17			; 00000011H
  00011	b8 cc cc cc cc	 mov	 eax, -858993460		; ccccccccH
  00016	f3 ab		 rep stosd

; 3    : 	char *ptr = "core dumped."; 

  00018	c7 45 fc 00 00
	00 00		 mov	 DWORD PTR _ptr$[ebp], OFFSET FLAT:??_C@_0N@LCLI@core?5dumped?4?$AA@ ; `string'

; 4    : 	*ptr = 'C';

  0001f	8b 45 fc	 mov	 eax, DWORD PTR _ptr$[ebp]
  00022	c6 00 43	 mov	 BYTE PTR [eax], 67	; 00000043H

; 5    : }

  00025	5f		 pop	 edi
  00026	5e		 pop	 esi
  00027	5b		 pop	 ebx
  00028	8b e5		 mov	 esp, ebp
  0002a	5d		 pop	 ebp
  0002b	c3		 ret	 0
_main	ENDP
_TEXT	ENDS

---

Для констант выделяется отдельный сегмент. А в релизе наверное подумали, что 4 килобайта (лишний сегмент) только для того, чтобы сунуть туда десяток байт - сильно расточительно и выглядит это так:

PUBLIC	_main
PUBLIC	??_C@_0N@LCLI@core?5dumped?4?$AA@		; `string'
;	COMDAT ??_C@_0N@LCLI@core?5dumped?4?$AA@
; File D:\Work\test\test.c
_DATA	SEGMENT
??_C@_0N@LCLI@core?5dumped?4?$AA@ DB 'core dumped.', 00H ; `string'
_DATA	ENDS
;	COMDAT _main
_TEXT	SEGMENT
_main	PROC NEAR					; COMDAT

; 3    : 	char *ptr = "core dumped."; 
; 4    : 	*ptr = 'C';

  00000	c6 05 00 00 00
	00 43		 mov	 BYTE PTR ??_C@_0N@LCLI@core?5dumped?4?$AA@, 67 ; 00000043H

; 5    : }

  00007	c3		 ret	 0
_main	ENDP
_TEXT	ENDS

---

Не знаю. Если записать побольше констант может им и выделят отдельный сегмент. В любом случае стандарт ничего об этом не говорит (отдает на откуп реализации).

Чтобы не надеяться ни на кого в Visual C можно использовать перед объявлением этой константы

#pragma const_seg(push, ".text")
и
#pragma const_seg(pop)

после

А можно и вообще слить секцию констант с секцией данных или кода (в опциях/ключах линкера или #pragma comment(linker, ...))

Это все касается vc, в остальных компиляторах нечто подобное тоже должно быть.

> > Это ж какой компайлер не понимает стандарта 98-го
> года?

> BCC V3.1 от 1992 года и SC V7.2 от 1995 года.
> Первый можно кастрировать до необычайно маленьких размеров
> так чтоб такать с собой буквально на дискетке. Второй
> правильно работает с памятью.

Флешки 128 метровые стоят меньше 20 баксов. Или дискеты это принципиально?

> Попробую.

Не забудь поколдовать над секцией констант, если эта константа глобальная или статическая (в функции/классе), если же это просто

struct A {
	int a;
};

void f(const A *a) {
	((A *)a)->a = 100;
}

int
main() {
	A *a = new A;
	A b;
	f(a);
	f(&b);
	return 0;
}

---

То бишь переменная выделена в обычной памяти, но const запрещает ее изменять, то преобразование типов - то что нужно.
1




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2024 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach