LINUX.ORG.RU

А как работает const ?

 


0

6

Все проверки делает компилятор С++ или переменная располагается в области памяти, защищенной от записи?



Последнее исправление: cetjs2 (всего исправлений: 1)

Ответ на: комментарий от Lzzz

Ладно, пока жру - побуду для тебя букварём.

Для начала, никакой памяти нет. Есть условное адресное пространство. Он виртуально. Адресуется оно(в рамках себя) не байтами, а страницами. Это такие блоки, от нескольких килобайт до нескольких гигабайт.

У это адресспейса есть права доступа, условно базовые rwx. Ты можешь их установить минимально на одну страницу.

Соответственно, никаким образом ты не можешь повесить ro на какой-то там объект - только минимум на страницу в которой он существует, либо на несколько страниц.

В рамках стека это сделать невозможно, в рамках аллокатора в общем случае тоже. Тебе нужно два стека. Двух стеков на х86 нет. Всё в дерьме.

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

Повторюсь - хочешь, делай. Но перед тем как рассказывать о «почему нету» - изучи букварь. Меньше будет ахренительной херни дошколятской.

tosol4152
()
Ответ на: комментарий от Lzzz

Эникей, зачем ты со мною споришь, если ты обречено?

.rodata and .rodata1

Это рудементарный мусор - его не существует. К тому же это статическое размещение, а не динамическое. Про семантическую константность тебе сообщили.

These sections hold read-only data

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

tosol4152
()
Ответ на: комментарий от tosol4152

Очевидно, что речь была не про тот конст, что появлется в сигнатурах ф-й или локальных переменных. Тебе про 100Мб, ты про стек. По опу понятно, что уж такой детсад ему не надо пояснять.

anonymous
()
Ответ на: комментарий от anonymous

А почему тогда если объявлять всё что можно const размер кода уменьшается?

Размер кода никого не волнует. Это наоборот плохо, что он уменьшается.

Это может быть обусловлено тем, что компиляторы - это такие С/С++ помойки у которых const может значить куда больше, чем он значит в языке. Это сделано и для расширений и для унификации.

Поэтому с каким-нибудь птушным уровнем оптимизации с которым собирается всякий мусор(на размер кода) - фронт может триггериться на const как на constexpr и выпиливать его.

Причин может быть много.

tosol4152
()
Ответ на: комментарий от Lzzz

Если сможешь получить доступ к такой памяти на запись, то да. Гарантии тут только уровня соглашений, что ты так делать не будешь, остальное зависит от того как реализовали. Это так же как и с квалификаторами доступа приватности, так же можно вытащить значения через указатели и приведения типа, хотя последнее тоже порицаемо, но в принципе в основном работает, особенно если знать как работает архитектура на который ты такое делаешь.

anonymous
()
Ответ на: комментарий от pavlick

const это не только ro память, а что более важно - ещё и зелёный свет компилятору на оптимизации.

Наличие/отсутствие const в параметрах не может влиять на оптимизации.

Помнится, ICC вставлял спекулятивную запись (точнее, выносил запись из-под условия, которое никогда на самом деле не выполняется) когда указатель был указателем на тип без const, что, естественно, приводило к падениям когда передавали указатель на данные в ro-области. За это интел был опиздюлен и в более новых версиях компилятора таких спекуляций себе не позволяет.

anonymous
()
Ответ на: комментарий от Lzzz

.rodata and .rodata1
These sections hold read-only data

Полезно посмотреть на elf через readelf, это

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000000040 0x0000000000000040
                 0x0000000000000268 0x0000000000000268  R      0x8
  INTERP         0x00000000000002a8 0x00000000000002a8 0x00000000000002a8
                 0x000000000000001c 0x000000000000001c  R      0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x00000000000007e0 0x00000000000007e0  R      0x1000
  LOAD           0x0000000000001000 0x0000000000001000 0x0000000000001000
                 0x0000000000000325 0x0000000000000325  R E    0x1000
  LOAD           0x0000000000002000 0x0000000000002000 0x0000000000002000
                 0x0000000000000180 0x0000000000000180  R      0x1000
...

 Section to Segment mapping:
  Segment Sections...
   00
   01     .interp
   02     .interp .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt
   03     .init .plt .text .fini
   04     .rodata .eh_frame_hdr .eh_frame
...

т.е. как сегменты мепятся на процесс. Нет в них ничего мистического, разница лишь в флагах (RW…) + некторые Program Headers будут размещаться рандомно (ASLR). В общем-то tosol это всё говорил, но так наглядно и можно пощупать.

ЗЫ: в рантайме нет сегментов, остаются лишь Program Headers.

pavlick ★★
()
Последнее исправление: pavlick (всего исправлений: 1)
Ответ на: комментарий от pavlick

Добавлю ещё кое что для мамкиных бенчеров. Там есть ещё одна фишка. Она перекликается с верой в «нужно всегда бенчить на рандомных данных».

Смысл в следующем. Всё, что лежит статически - аллоцируется mmap"ом и в основном инициализировано нулями(т.е. никак не инициализировано).

Потом, когда адепт начинает читать память, которая не была никем записана - происходит следующие. У ядра есть специальная нулевая страница и оно тупо подключает её ко всем адресам. И в результате неважно сколько у тебя памяти - хоть терабайт - в реальности её будет 4k. И производительность у неё будет соответствующая.

И если выделить этот же кусок маллоком(с терабайтои уже не прокатит, потому как он форвардится в mmap, а с мелкими кусками прокатит) - там с высокой долей вероятности вернётся память, которую уже кто-то писать. А если там кусок менее 4k - шанс 100%.

И со стеком тоже самое. Там так же почти всегда будет память, в которую уже кто-то писал.

И подобные эффекты адепты могут где-то увидеть, но всё перепутать и решить, что это свойство каким-то там сегментом. И именно для того, что-бы не ловиться на подобную херню - нужно изучать нюансы.

tosol4152
()
Ответ на: комментарий от tosol4152

И со стеком тоже самое. Там так же почти всегда будет память, в которую уже кто-то писал.

Со стеком ещё интересней - так называемый «мусор» в неинициализированных переменных - результат деятельности ASLR захламляющий стек разными адресам возврата от запуска к запуску (кстати, под gdb ASLR не работает). Ну я это не для тебя.

pavlick ★★
()
Ответ на: комментарий от cherry_boy

const int b = 1;

Дедовский способ с таким хаком бороться:

register const int b = 1;
anonymous
()
Ответ на: комментарий от Lzzz

Ведь компилятор когда видит, что пытаются получить адрес const переменной

Какая разница видит, или нет? Там же каст, т.е. прямое указание «считай так».

no-such-file ★★★★★
()
Ответ на: комментарий от tosol4152

рудементарный

В школу, тебе сообщили уже

/0 в анус себе сообщи, орфографическим словарем те по еблу

anonymous
()
Ответ на: комментарий от t184256

Какой дедушка лучше Ленин или Сталин?

anonymous
()
Ответ на: комментарий от Lzzz

Блин и в чем тут разница? Ведь компилятор когда видит, что пытаются получить адрес const переменной, он не может заменять ее значением?

Компилятор может находить UB в constexpr и выдавать ошибки компиляции.

G++ can now detect modifying constant objects in constexpr evaluation (which is undefined behavior).

https://gcc.godbolt.org/z/ZR3RVT

fsb4000 ★★★★★
()
Ответ на: комментарий от tosol4152

Никаких ro-областей нет

да как же ты задолбал, школьник безграмотный.

прочисти уже говно из башки и узнай что мир не ограничен x86 дерьмом.

anonymous
()
Ответ на: комментарий от Lzzz

Но есть вызов mprotect() system call sets the access protections for the pages that contain the address range addr through addr + len - 1. Что не дает компиляторы объекты const разместить в нем?

mprotect - юниксоидная хрень и костыль, а C++ (внезапно!) не ограничен этими вашими позиксами?

seiken ★★★★★
()
Последнее исправление: seiken (всего исправлений: 1)
Ответ на: комментарий от anonymous

Что-то выкидывается из кода или константы с одним и тем же значением заменяются одной глобальной переменной.

anonymous
()
Ответ на: комментарий от Lzzz

Разница простая.
Когда переменная глобальная, она размещается в read-only секции констант, а во втором случае она лежит просто на стеке и технически не отличается от обычных переменных. Это в общем-то логично, т.к. такая константа существует только во время вызова функции и на самом деле может быть нифига не константой, получая свое значение во время вызова функции а-ля

void f(char *c)
{
    const size_t len = strlen(c);
    ...
}
Также стоит обратить внимание на
void f(const char *c)
{
    ...
}

int main(int argc, char *argv[])
{
    char buf[1024];
    f(buf);
    return 0;
}
Улавливаешь теперь суть? Спецификатор const внутри функций - это больше на уровне соглашений, чем реально const.

cherry_boy
()

Люди здесь пишут, время удиляют, пытаются помочь, а автору глубоко фиолетово, никакой обратной связи. Вряд ли буду ещё ввязываться в подобное, какие-то темы ради холивара.

pavlick ★★
()
Ответ на: комментарий от pavlick

Так и есть, автор сюда уже пришел прекрасно зная как обстоят дела с const, но почему бы не набросить то, когда можно набросить?

anonymous
()
Ответ на: комментарий от pavlick

Увы это не работает, тут зачастую некропостят в темы давности в пару месяцев, вы давая «свое решение» и голубая галочка им не помеха. Нужно просто закрывать такие темы которые решены по мнению автора темы и закрывать он их должен сам, а раз не закрывает - то наброс.

anonymous
()
Ответ на: комментарий от anonymous

А простите лор может закрыть только с удаление модераторской рукою, ну тогда вопросов нет, лор во всем виноват.

anonymous
()
Ответ на: комментарий от pavlick

Это не указание на оптимизацию, в Вашем примере. А запрет на изменение.

А оптимизация может быть только с объявленными константами. Когда, например, при сложении, константа следует вместе с кодом, а не вытаскивается из памяти. Что, собственно, оптимальнее.

addq (%rdi), %rax

vs

addq $4, %rax

Что, вероятно, Вы и имели ввиду. Или догадывались о.


P.S.: только что меня посетила мысль, что ссаная гугл-капча спрашивает «я не робот»; т.е. её не волнует – человек это или чудовище.

anonymous
()
Ответ на: комментарий от anonymous

У тебя проблема с методичкой. Если у тебя доступно объявление - оптимизатор и так знает константа там или нет. Никто не строит анализатор на базе хинтов дерьма для птушников.

Я тебе даже открою причину почему. В любом случае за этой константой нужно следить, ведь оптимизировать нужно контекст её использовать. Поэтому она может алиасится через копии/ссылки и прочее.

В результате ты будешь иметь что-то типа литерал -> хинт_говна -> тысячи аласов -> использование. И нужно пройти по всем этим цепочках, проталкивая константу. Но, о чудо, а нахрен? Если всегда можно пройти дальше и найти источник, которые будет литерал? Который константный. Да и не константное значение, если оно не изменяется - тоже константное.

Поэтому любой оптимизатор не дерьма никогда не будет полагаться на хинты дерьма. Просто потому, что этот оптимизатор обязан выявлять сам эти константы. А если он не делает этого - он говно. А если он уже умеет это делать - результаты его работы всего надёжнее, нежели твоё ручное говно.

Но самое интересное, что даже на ручном говне он не может останавливаться. Потом как если у тебя есть код:

  const v = 123;
  const x = v;
  const y = v;

То если оптимизатор будет останавливаться на хинте, то он никогда не узнает, что x и y - алиасы, а значит будет генерировать две одинаковые константы, засирая память, регистры и прочее.

anonymous
()

а в чем проблема скомпилировать и потом открыть бинарник в IDA Pro посмотреть что там там происходит?

xmikex ★★★★
()

Тред не читал. const защита от дурака. Где-то читал статью, наверное на хабре, где на движке БД проверяли влияние const на оптимизации компилятора. Нихера существенного не вышло.

ox55ff ★★★★★
()
Ответ на: комментарий от ox55ff

Щас бы на I/O-bound программе проверять оптимизации.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.