Comments 39
Ужас какой-то)
0
Язык с указателями + продвинутая оптимизация — всегда гремучая смесь.
+3
Имхо, всё ок, как и во многих языках есть пулинг ресурсов для экономии памяти, просто в Objective-C можно unsafe вещи с памятью делать.
В Java, например, можно всю программу разломать, если рефлекшеном поменять значение какого-нибудь числа из пула констант, математика к чертям полетит.
+ Не знаю, как в Objective-C, но в Java можно ещё дров наломать если синхронизироваться на расшаренном объекте, например, так:
Я даже статью на эту тему писал: "Story of one dependency injection in Telegram Android App"
В Java, например, можно всю программу разломать, если рефлекшеном поменять значение какого-нибудь числа из пула констант, математика к чертям полетит.
+ Не знаю, как в Objective-C, но в Java можно ещё дров наломать если синхронизироваться на расшаренном объекте, например, так:
Скрытый текст
// Integer Pool! Никогда так не делайте
Integer lock = 1;
synchronized(lock) { ... }
Я даже статью на эту тему писал: "Story of one dependency injection in Telegram Android App"
+3
Это типа можно в военное время поднять значение пи до четырех, а по особому указанию партии — и до пяти? ;)
Простите, я не в курсе: константы в Java — глобальные?
Простите, я не в курсе: константы в Java — глобальные?
+3
Можно например сделать 2 + 3 == 4, если через рефлекшн поменять 2 на 1 или 3 на 2.
Пул констант есть для целых чисел [-128, 127], для float/double, насколько я знаю, пула нет.
Так же есть пул строк, поведение такое же, тоже можно патчить через рефлекшн заменить «hello world» на -> «пшел отсюда» без проблем :)
«Константы в Java — глобальные?» немного не понял вопрос, вообще нет, всё должно быть в рамках определенного класса
Пул констант есть для целых чисел [-128, 127], для float/double, насколько я знаю, пула нет.
Так же есть пул строк, поведение такое же, тоже можно патчить через рефлекшн заменить «hello world» на -> «пшел отсюда» без проблем :)
«Константы в Java — глобальные?» немного не понял вопрос, вообще нет, всё должно быть в рамках определенного класса
+2
Переформулирую. Можно ли поменять константу в одном модуле/классе и неожиданно нарваться на изменившееся значение в другом? В моем примере это именно так происходит: функцию bad() можно зарыть в произвольное место проекта.
0
void bad(){
NSString* a = @"123456789";
char* aa = (__bridge void *)(a);
aa[8] = 92;
}
да вы в любом объекте в кишках поковыряйтесь и ему плохо станет
это же не строка char* в понимании С, что можно тупо от начала массива смещениями скакать… афтор сам ничего не понял походу
+5
В том, плохо станет тому объекту, в котором поковыряли, — ничего удивительного, я не подвергаю это сомнению. Неожиданно то, что плохо станет и объектам, существующим в другой области видимости, созданным отдельно и никак формально с подвергшимся вмешательству не связанным.
+4
Да, пожалуй это и нелогичное поведение, но очень справедливое. Вы кастуете объект непонятно к чему, делаете какие-то странные манипуляции, а ожидаете чего-то вменяемого?
Не уверен конечно, но подозреваю что подобное поведение не определено, а потому произойти может что угодно.
Радуйтесь что вас динозавр не унес.
Не уверен конечно, но подозреваю что подобное поведение не определено, а потому произойти может что угодно.
Радуйтесь что вас динозавр не унес.
+1
С моей точки зрения ожидаемым поведением было бы то, что все, что я накастовал в пределах локальных переменных какой-то функции какого-то модуля, не окажет глобального влияния на локальные переменные других областей видимости. Ну или пусть меня действительно динозавр унесет: программа вывалится с Segmentation Fault или еще как-то.
Совершенно с вами согласен, что получать по рукам за стремные манипуляции с объектами — справедливо. Предлагаю рассматривать статью как (забавную, на мой вкус) иллюстрацию к этому правилу.
Совершенно с вами согласен, что получать по рукам за стремные манипуляции с объектами — справедливо. Предлагаю рассматривать статью как (забавную, на мой вкус) иллюстрацию к этому правилу.
+4
UFO just landed and posted this here
Если честно, статья не «об одном способе выстрелить себе в ногу», а рассказывает о том, как:
купить дробовик, проверить его, зарядить, тщательно прицелиться и выстрелить в ногу.
Менять значение указателя на объект по смещению в расчете на то, что по этому адресу реально хранится строка
(а не какая-нибудь служебная информация типа той же кодировки) — это очень странно.
купить дробовик, проверить его, зарядить, тщательно прицелиться и выстрелить в ногу.
Менять значение указателя на объект по смещению в расчете на то, что по этому адресу реально хранится строка
(а не какая-нибудь служебная информация типа той же кодировки) — это очень странно.
+5
Скорее она о том, как вы стреляете себе в ногу, а попутно простреливаете голову, хотя она ну никак не могла на пути пуль оказаться
+7
Отличная метафора, спасибо :)
+3
Я бы уточнил — стреляете себе в правую ногу, а отстреливаете обе, потому что левая — алиас правой.
+1
нет, указатель не должен быть алиасом константы.
0
Речь об объекте, полученном из литерала (и указателях на этот объект), а не о самом литерале.
0
О неизменяемом на первый взгляд объекте, который, оказывается, можно испортить из любого места кода
0
Я думаю, «проблема» тут скорее в том, что люди интуитивно преполагают, что объектов там столько же, сколько и литералов. Т.е. внезапным оказывается не то, что NSString можно изменять через хитрые касты, а то, что при этом изменяется какой-то «другой» NSString (который на самом деле тот же самый). То есть «проблемой» является именно алиасинг, а не нарушение иммутабельности.
0
>Чтобы разместить строки в heap, где они могут быть изменены, нужно заменить char *a на char a[]
Разве не наоборот?
Разве не наоборот?
+1
Вроде бы нет. Там даже по изменению адресов видно, где лежат строки в одном и в другом случае. c-faq.com/decl/strlitinit.html
0
Аналогичную оптимизацию строковых констант выполняет и gcc при компиляции кода на Си. Например,
#include <stdio.h>
void main(){
char *a = «123456789»;
char *b = «123456789»;
printf("%p %p\n", a, b);
}
Здесь к char * надо добавить const что бы дальнейшие рассуждения были верными
#include <stdio.h>
void main(){
char *a = «123456789»;
char *b = «123456789»;
printf("%p %p\n", a, b);
}
Здесь к char * надо добавить const что бы дальнейшие рассуждения были верными
0
UFO just landed and posted this here
clang под Ubuntu на LLVM 3.4 действительно создаст три различных объектаа как вы это делаете? В смысле, Foundation же нет для linux?
0
То есть, чтобы заменить одну константу на другую, достаточно сделать:
Теперь в любом месте, где встречается @«123» будет выводиться @«2345678»:
(во всяком случае для arm64)
uint64_t *i = (__bridge void*)@"123";
uint64_t *j = (__bridge void*)@"2345678";
i[1] = j[1];
Теперь в любом месте, где встречается @«123» будет выводиться @«2345678»:
NSLog(@"123"); // 2345678
(во всяком случае для arm64)
0
Sign up to leave a comment.
Особенности создания NSString