- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
#include <stdio.h>
#include <stdlib.h>
int * ptr;
int * getptr()
{
puts("getptr");
return ptr;
}
int jump()
{
puts("jump");
ptr = (int*)malloc(sizeof(int));
return 1337;
}
int main()
{
ptr = (int*)malloc(sizeof(int));
*ptr = 0;
*( getptr() ) = 1;
printf( "*ptr = %i\n\n", *ptr );
*( getptr() ) = (jump(), 100);
printf( "*ptr = %i\n\n", *ptr );
*( getptr() ) = jump();
printf( "*ptr = %i\n\n", *ptr );
return 0;
}
bugspawn 15.11.2017 00:06 # −1
roman-kashitsyn 15.11.2017 00:26 # +3
Пример с 100 работает из-за наличия "точки следования" в виде оператора ,
bugspawn 15.11.2017 01:16 # 0
- частично вычисляется левая часть = (выполняется getptr())
- вычисляется правая часть (выполняется jump())
- продолжает вычисляться левая часть (выполняется *)
не, ну это КАК ВООБЩЕ?
т.е. есть оператор =, у него 2 операнда, и компилятор такой взял чучуть посчитал слева, потом чучуть справа, потом подумал решил снова влево посчитать
тест №2:
- вычисляется правая часть (выполняется jump() и ",")
- вычисляется левая часть = (выполняется getptr() и потом *)
каким таким боком "," внутри правого операнда влияет на то, когда в левом операнде будет посчитано значение в скобках (getptr()) - до или после вычисления правого операнда???
SemaReal 15.11.2017 01:21 # +3
Это же UB, он имеет право что угодно сделать. При включенной оптмизации компелятор вообще может выкинуть UB код: дескать можно вообще ничего не делать, раз UB.
Dummy00001 15.11.2017 19:29 # 0
правильнее: что бы разрешить компилерам делать что угодно (== агресивная оптимизация вызовов функций), стандарт оставляет это как UB.
subaru 15.11.2017 22:18 # 0
Dummy00001 15.11.2017 22:23 # 0
я не говорил про общий случай. я говорил про конкретный случай, проиллюстрированый в говнокоде.
стандарт может сделать корректным код сверху, но это преднамеренно не делается.
subaru 15.11.2017 22:30 # 0
Dummy00001 16.11.2017 00:05 # +1
WAS THIS PAGE HELPFUL? YES/NO. TELL US MORE. YOUR OPINION IS IMPORTANT TO US!
Antervis 16.11.2017 11:41 # 0
j123123 07.12.2017 18:14 # 0
inkanus-gray 08.12.2017 00:17 # 0
В процессорах x86 есть похожий хак: инструкция LEA. Она тоже не читает данные, а просто вычисляет их адрес.
j123123 08.12.2017 00:53 # 0
> Принципиально то, что синтаксический сахар, теоретически, всегда можно удалить из языка без потери его возможностей — всё, что можно написать с применением синтаксического сахара, может быть написано на этом же языке и без него. Таким образом, синтаксический сахар предназначен лишь для того, чтобы сделать более удобным для программиста написание программы.
Допустим:
И как это переносимо написать без sizeof? Создавать массив из двух элементов struct shit и вычитать разницу адресов между нулевым и первым элементом для такого массива? Такой подход будет неточным.
Для одной структуры с учетом выравниваний полей допустим будет такая хуита:
Но если сделать массив из двух таких структур, этот uint8_t e уже сожрет себе все 4 байта, и разница между одним и другим указателем в массиве из двух таких структур будет не равна размеру одной структуры в байтах
j123123 08.12.2017 01:01 # 0
bormand 08.12.2017 07:20 # 0
j123123 08.12.2017 13:26 # 0
bormand 08.12.2017 19:46 # +1
g0cTb 08.12.2017 01:49 # 0
1) равна, т.к. размер структуры включает паддинги
2) и соответственно sizeof возвращает ровно количество байт между двумя структурами в массиве
j123123 08.12.2017 02:44 # 0
g0cTb 08.12.2017 12:48 # 0
j123123 08.12.2017 13:21 # 0
roman-kashitsyn 08.12.2017 13:33 # 0
Ты же знаешь, что ОС всё равно блоками пишет, да?
j123123 08.12.2017 13:35 # 0
j123123 08.12.2017 13:54 # +1
Вобщем-то сишечка довольно убогий язык, но в плюсах-то эту проблему решили же, да?
roman-kashitsyn 08.12.2017 14:07 # 0
Я так и делал всегда. Там же строки могут быть, указатели, вот это всё. Плюс byte order иногда важен. Просто пишешь простенький сериализатор/десериализатор и не выёживаешься. Ну или просто используешь какой-нибудь asn1/protobuf.
j123123 11.12.2017 03:21 # +1
> Там же строки могут быть, указатели, вот это всё.
Можно придумать некий внутриязыковой механизм, который бы позволял программировать все такие вариации, скажем
В общем тут как раз таки гомоиконность нужна. В плюсах есть лишь какие-то ограниченные костыли, вроде констэкспров, шаблонов. Есть ли какие-нибудь способы распарсить в компилтайме тип структуры (из чего она состоит) и на основе этого порождать некий код, который что-то там должен делать?
bormand 11.12.2017 07:54 # 0
Пока только ограниченное говно типа boost::fusion, где поля надо руками перечислять (типы само надёргает).
Но обещают завезти нормальную рефлексию и кодогенерецию. Лет через 5-10.
subaru 11.12.2017 12:40 # +3
а завезут метушню
nemyx 08.07.2020 09:51 # 0
guest8 08.07.2020 10:16 # −999
nemyx 08.07.2020 10:22 # 0
roman-kashitsyn 11.12.2017 12:53 # 0
У кодогенераторов есть преимущество: они могут генерить код на разных языках из одного описания.
bormand 11.12.2017 18:10 # 0
Правда при этом приходится добавлять ещё один язык для таких описаний...
roman-kashitsyn 11.12.2017 18:19 # 0
... что не обязательно является чем-то плохим.
Antervis 11.12.2017 19:18 # +1
roman-kashitsyn 11.12.2017 19:54 # +1
Так-то в каком-нибудь CL можно один раз написать макрос и генерить из сериализаторы/десериализаторы/парсеры/валидаторы/модули для nodejs/даже небо/даже аллаха. Но люди продолжают придумывать новые, более другие языки.
SemaReal 08.12.2017 04:39 # 0
j123123 08.12.2017 05:03 # 0
SemaReal 10.12.2017 21:18 # 0
иными словами sizeof(*bar) всегда есть sizeof(bar) даже если bar это данглинг поинтер?
Ну звучит логично: не надо разыменовывать
Antervis 08.12.2017 17:22 # −1
subaru 15.11.2017 22:21 # 0
bugspawn 15.11.2017 01:21 # 0
roman-kashitsyn 15.11.2017 01:27 # +2
SemaReal 15.11.2017 01:31 # 0
В swift, я думаю, что тоже UB нет (во всяк случае ябловый UBSanitizer в шланге работает только для C)
j123123 15.11.2017 02:46 # 0
Но UB там возникает не на ровном месте, в отличии от плюсов и сишки
SemaReal 15.11.2017 02:48 # 0
ну так-то оно и в Java есть sun.misc.Unsafe
Даже в питоне можно взять cTypes и стригеррить черте-что
Мы же про "нормальное" использование языка.
j123123 15.11.2017 02:58 # 0
> Если кратко, то содержание поста сводится к рассмотрению следующего примера:
> Строка в C# представляет собой последовательность слов в UTF-16. А значение "X\ud800Y" не особо хорошее, т.к. включает в себя старшее слово суррогатной пары 0xD800, после которого должно бы идти младшее слово (интервал 0xDC00..0xDFFF), но вместо него идёт Y (0x0059). Проблемы начинаются из-за того, что в IL-коде для хранения аргументов конструктора атрибута используется UTF-8. Впрочем, у Джона Скита всё очень хорошо расписано, всем советую прочитать оригинальный пост.
> Меня заинтересовало, как же будут себя вести MS.NET и Mono в этой непростой ситуации (подробная заметка). А вести они себя будут по-разному. Первое различие можно увидеть во время компиляции. MS.NET положит значение строки в метаданные в виде 58 ED A0 80 59, а Mono — в виде 58 59 BF BD 00 (оба значения являются невалидными UTF-8 строчками). Второе различие можно пронаблюдать запустив полученные приложения. MS.NET сможет запустить обе версии и успешно достанет значение аргумента атрибута (в виде 0058 fffd fffd 0059 и 0058 0059 fffd fffd 0000 соответственно), а Mono поперхнётся настолько невалидной строкой и вернёт null в каждом из случаев. Из-за этого маленький пример Джона Скита сразу упал, когда я попытался запустить его под Mono.
j123123 15.11.2017 03:01 # 0
SemaReal 15.11.2017 03:19 # 0
Это дыра в стандарте
[quote]
According to the ECMA-334 document (p. 473):
A program that does not contain any occurrences of the unsafe modifier cannot exhibit any undefined behavior.
[/quote]
Но вообще мой cl четко видит тут три буквы: первая и последняя обычные, а средняя занимает 3 байта в UTF-8 (мне кажется это какой-то такой плейн где всякие asian languages, а нет, это невалидная хуйня (которую уникод обозначает значком [?]) )
d_fomenok 15.11.2017 19:22 # 0
Это не UB
SemaReal 15.11.2017 23:12 # 0
SemaReal 15.11.2017 01:36 # +5
bugspawn 15.11.2017 01:50 # 0
SemaReal 15.11.2017 02:28 # +1
Ведроид бывает
1) не только на arm (mips, atom)
2) 90% софта там писано на java/kotlin под ART. А там действуют правила JMM и JLS.
зы: ну ты понимаешь же что с weak memory model можно прекрасно жить, как и с любой другой memory model, главное не завязываться на странные спец-эффекты.
Любой CPU всегда можно попросить не реордерить ничего (обычно с помощью интринсика или ключевого слова ЯПа, которое затем превращается в инструкцию типа fence или как-то так)
bugspawn 15.11.2017 04:38 # 0
понятно что жить можно и любой подводный камень можно переступить
но должно же быть какоето объяснение феномену...
на вики пишут что косяки JMM с 2004 года недействительны
SemaReal 15.11.2017 05:13 # +2
У JMM нет UB кроме race conditions, но это не совсем UB так как не зависит от компилятора (а зависит от количества ядер, шедулера операционной системы, количества и тяжести других процессов, и месяца китайского календаря).
Объяснение очень простое: чем слабее гарантии -- тем больше свободы у инженеров в разработке проца, а значит тем лучше он у них может получиться.
Ты ведь наверное тоже не любишь делать свои интерфейсы и API публичными, что бы на них сразу же завязались 150 человек, и ты бы потом не мог их отрефакторить
Stallman 16.11.2017 00:09 # −1
Там всё, как тебе нравится: https://ideone.com/IY0KUp
inkanus-gray 16.11.2017 00:12 # −1
Stallman 16.11.2017 00:15 # −1
inkanus-gray 16.11.2017 00:36 # −1
Stallman 16.11.2017 01:03 # 0
Напрямую к ним обратиться нельзя - это синтаксически неверно. Но если использовать $$, то именем переменной может быть любая строка и, следовательно, что угодно, что в нее конвертится.
https://ideone.com/svS2sO
inkanus-gray 16.11.2017 01:21 # 0
P.S. Это можно публиковать отдельным говнокодом.
Stallman 16.11.2017 01:44 # −1
j123123 16.11.2017 21:12 # +1
SemaReal 16.11.2017 21:18 # +1
subaru 16.11.2017 22:03 # 0
SemaReal 17.11.2017 15:59 # 0
Bobik 16.11.2017 22:29 # 0