Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Поймать факт перезаписи
|
|||
|---|---|---|---|
|
#18+
Lumix что касается примеров b() = new A, то это просто заглушка. в реале на уровне пользователя используются только функции b() = a(); и пользователь не должен думать, что же там под капотом происходит и не потечет ли у него что-нибудь... Есть такой патерн , называется виртуальный конструктор, Делайте там методы create_object, get_object, delete_object итд и пусть через него кто как хочет тот так и управлеяет обьектами. Какую сигнатуру определите так и будет управляться. Зачем вы нам пудрите мозги с желанием запрятать под капот указатели и ссылки. Прячьте их под патерн. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.12.2012, 20:22 |
|
||
|
Поймать факт перезаписи
|
|||
|---|---|---|---|
|
#18+
LumixИ да и нет. ))) На мой взгляд ключевой критерий GC - асинхронность событий: перестал быть нужен и решили удалить, а в случае, который обсуждается в этой теме удаление происходит сразу, как только мы решили его удалить, в данном случае приказом на удаление является присвоение указателя А ты не боишся что требование удалять сразу является ударом по производительности? Может быть создатели GC были не дураки и неспроста сделали освобождение памяти для обнулившейся ссылки (обнулившийся счётчик связей) отложенным? Ты думал об этом? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.12.2012, 20:36 |
|
||
|
Поймать факт перезаписи
|
|||
|---|---|---|---|
|
#18+
LumixС очень простых делов: он занял его указатель!! И это таки мировая проблема в конкретной задачи. Объект не занимал ничей указатель. Вдумайтесь что есть объект, что он занимает, а что есть указатель на объект, и какое к нему отношение имеет сам объект? Никакого. Указатель имеет отношение к объекту (он на него указывает). А объект к указателю - не имеет. Не знает о нем ничего. Более того, при создании объекта никого указателя нет. Есть создание объекта в памяти. А потом уже в указатель записываем адрес на эту память. При чем, ранее в этом указателе могло быть значение и факт того, что теперь в нем новое значение, еще не означает необходимость удалять прежний объект. Не новому объекту решать, нужен еще старый кому-то или уже никому не нужен. Это бред. И не важно, что именно в вашей задачи именно сейчас этот бред пока что имеет некоторый смысл. Это все-равно бред. А завтра еще и источник невероятных паранормальных явлений в вашем приложении. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.12.2012, 20:39 |
|
||
|
Поймать факт перезаписи
|
|||
|---|---|---|---|
|
#18+
ДохтаРLumix что касается примеров b() = new A, то это просто заглушка. в реале на уровне пользователя используются только функции b() = a(); и пользователь не должен думать, что же там под капотом происходит и не потечет ли у него что-нибудь... Есть такой патерн , называется виртуальный конструктор, Делайте там методы create_object, get_object, delete_object итд и пусть через него кто как хочет тот так и управлеяет обьектами. Какую сигнатуру определите так и будет управляться. Зачем вы нам пудрите мозги с желанием запрятать под капот указатели и ссылки. Прячьте их под патерн. У меня нет задачи пудрить вам мозги!! Я готов реализовать что угодно, лишь бы спрятать от пользователя все сложности плюсовой архитектуры. Объясните мне что именно вы имели ввиду под "create_object, get_object, delete_object"??? и я сделаю это если вы имели ввиду давать эти методы в руки пользователей, то это 100% НЕТ!! задача стоит чтобы они вообще забыли, что работают с какими-то объектами, что надо какую-то память выделять и что есть какие-то правила при переносе объектов между функциями. все это надо скрыть навсегда пользователи не должны управлять объектами!! попробуйте попрограммировать на яваскрипте и поймете, что я имею ввиду ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.12.2012, 20:43 |
|
||
|
Поймать факт перезаписи
|
|||
|---|---|---|---|
|
#18+
maytonА ты не боишся что требование удалять сразу является ударом по производительности? Может быть создатели GC были не дураки и неспроста сделали освобождение памяти для обнулившейся ссылки (обнулившийся счётчик связей) отложенным? Ты думал об этом? 1. Нет, я этого не боюсь 2. Я оооочень серьезно обдумал все это. Первый раз когда я задумался "о смысле жизни"))) то есть о памяти, о gc и все такое это было где-то 2008-2009 год. То есть я так или иначе возвращаюсь к этой теме уже 3-4 года, потому что каждый новый успешно реализованный проект дает возможность посмотреть на эти задачи под новым более широким углом и соотв. решать более красиво. насчет "мудрости GC архитекторов"... ответ на ваш вопрос очень прост: они сделали отложенным очистку по одной простой причине: она автоматическая и если она будет включатся, когда ей вздумается, то она может слегка подвесить рантайм что касается нашего варианта, то а) я не согласен называть его GC вариантом (причины уже изложил выше) б) пользователь сам решает когда вызывать delete stage75(); и этот вызов он спланирует так, чтобы с прикладной точки зрения это было наиболее выигрышно. классический пример: уровни в компьютерных играх: закончился уровень, почистили его и загрузили ресурсы нового уровня что же касается обсуждаемой задачи Код: plaintext 1. то тут а) падения нагрузки не будет б) если кто-то по дури захочет совершить такой трюк с деревом объектов на 450 мб))) то этот факт обязательно заметят, очень быстро найдут и устранят. обращаю внимание: это факт, а не баг!! это задача оптимизации работы программы, а не задача отладки короче, вопросы скорости тут не критичны ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.12.2012, 20:52 |
|
||
|
Поймать факт перезаписи
|
|||
|---|---|---|---|
|
#18+
Edd.Dragon, я 100% понял что вы имеете ввиду, но ваши логические комбинации из речевых конструкций скорее мотивированны получением удовольствия от концептуальных форм, чем от решения конкретной задачи, тогда как если сделать конкретную задачу критерием логики, тогда часть ваших конструкций теряет силу... Edd.DragonОбъект не занимал ничей указатель. Код: plaintext 1. 2. второй объект занял указатель первого объекта Edd.DragonВдумайтесь что есть объект, что он занимает, а что есть указатель на объект, и какое к нему отношение имеет сам объект? Никакого. Я понимаю какие эмоции удовольствия вы испытываете от концептуальной валидации моих решений, но приоритет прикладной проверки каждой концепции лишает меня смысла вдумываться в корректность используемых знаков. Объект это просто участок памяти, а указатель это переменная которая хранит адрес на участок в памяти. В рамках обсуждаемой темы, я подчеркивают только в рамках обсуждаемой задачи, указатель считается принадлежащим тому объекту, на который он ссылается. Код: plaintext 1. 2. именно поэтому в данной задаче можно сказать, что второй объект занял указатель первого, тогда как попытка проверить валидность этих утверждений с точки зрения общей концепции языка программирования, разумеется обречена на провал именно поэтому я в очередной раз призываю отказаться от расширения области действия используемых речевых конструкций (слов, если угодно сигнатур) Edd.DragonУказатель имеет отношение к объекту (он на него указывает). А объект к указателю - не имеет. Не знает о нем ничего. Сама тема возникла из-за того, что это так. И тема создана, а как это исправить. Вы мне как бы пытаетесь объяснить, что кусок металла весом 1 тонну не может сам улететь в космос, потому что есть гравитация. А я пришел сюда узнать как использовать ракетные двигатели, то есть как можно преодолеть ограничение. Edd.DragonБолее того, при создании объекта никого указателя нет. Есть создание объекта в памяти. А потом уже в указатель записываем адрес на эту память. Его нет в общем случае, но в нашей конкретной ситуации он есть!! и есть всегда! Код: plaintext 1. 2. Edd.DragonПри чем, ранее в этом указателе могло быть значение и факт того, что теперь в нем новое значение, еще не означает необходимость удалять прежний объект. В общем случае да, но в нашем случае это 100% обозначает, что удалять надо, потому что начальное значение указателя всегда 0 и если оно не 0, значит там есть объект!! Edd.DragonНе новому объекту решать, нужен еще старый кому-то или уже никому не нужен. Это бред. Это не бред, а задача.))) А вот кому решать новому, старому или какой-то иной внешней конструкции это и будет решением задачи. Но решение о том, что прежний объект надо убить это решение принимаю я как архитектор системы и я его уже принял, сформулировав в виде задачи. Edd.DragonИ не важно, что именно в вашей задачи именно сейчас этот бред пока что имеет некоторый смысл. Это не просто важно, а это единственное, что имеет значение. В рамках нашей компании других источников важности просто не существует. Я есть высший источник всякой важности, точно так и вы, если конечно вы являетесь не рядовым исполнителем, тоже принимаете окончательное решение что важно, а что вторично. Edd.DragonЭто все-равно бред. Опять же все зависит от системы координат. Наши проекты и задачи являются бредом для вас точно так же как для вас может являться бредом речь на вьетнамском языке. Именно поэтому я в который раз отказываюсь выходить за пределы задачи и дискутировать на какие-то темы в чьих-то чужих контекстах, к которым относятся всякие "а что если..." и "а вдруг нам понадобится..." Edd.DragonА завтра еще и источник невероятных паранормальных явлений в вашем приложении. А вы знали, что чисто статистически 99% событий, которых опасаются люди, не случаются вообще, а те опасные события, которые и случаются, то они часто оказываются примерно в 10 раз тусклее по опасности, чем рисовало воображение, а все подлинные катастрофы происходят тогда и оттуда, откуда никто никогда не ожидал даже принципиально!! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.12.2012, 21:17 |
|
||
|
Поймать факт перезаписи
|
|||
|---|---|---|---|
|
#18+
Lumixтолько почему-то shared не хочет принимать через равно внутренний объект, переданный ему через указатель... это чё мне перегрузку шареда надо мутить, да?? Какая еще перегрузка шареда. Смена объекта в смарт-указателе делается через функцию reset(). Код: plaintext 1. 2. 3. Но правильнее вообще не использоваять явно new, а создавать объекты через make_shared (<boost/make_shared.hpp>). Код: plaintext 1. 2. 3. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.12.2012, 21:45 |
|
||
|
Поймать факт перезаписи
|
|||
|---|---|---|---|
|
#18+
авторИ тема создана, а как это исправить. Это какое-то издевательство ))) Lumix пользователи не должны управлять объектами!! Так на кой же вы им даете прямой доступ к чертовым указателям внутри контейнера? Почему мы только на "третий день" узнаем, что дело не в автоподтирании, а в том, что у вас какие-то проблемы с инкапсуляцией и вы не хотите видеть ее в общепринятом виде? Пока вы не объясните причины этого, то таки это будет выглядеть как глупость, бред и возжа под хвост. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.12.2012, 21:56 |
|
||
|
Поймать факт перезаписи
|
|||
|---|---|---|---|
|
#18+
Edd.DragonЭто какое-то издевательство ))) Вам уже хочется меня ударить?? ;) Я так-то хороший... могу и просто в сторонку отойти, если градус накаляется...))) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.12.2012, 22:02 |
|
||
|
Поймать факт перезаписи
|
|||
|---|---|---|---|
|
#18+
LumixВам уже хочется меня ударить?? ;) Нет - хочется правды об этом таинственном интерфейсе! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.12.2012, 22:05 |
|
||
|
Поймать факт перезаписи
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyКакая еще перегрузка шареда. Смена объекта в смарт-указателе делается через функцию reset(). Хорошо, reset(), супер, отлично. make_shared<>() круто, ништяк. Но как мне эти штуки запаковать под капот, чтобы все работало по форме Код: plaintext 1. тут хотя бы оператор равно появился - уже круто Код: plaintext 1. как теперь можно спрятать этот make_shared, чтобы остался только = new A надо class B менять или прирастить к shared_ptr::operator+()?? или может под мой случай какую-то свою легкую версию шареда написать?? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.12.2012, 22:11 |
|
||
|
Поймать факт перезаписи
|
|||
|---|---|---|---|
|
#18+
Edd.DragonТак на кой же вы им даете прямой доступ к чертовым указателям внутри контейнера? А как по вашему они должны юзать функции этих объектов-то?? под фразой юзеры не должны управлять объектами я имел ввиду они не должны управлять ими в памяти, но разумеется они управляют конфигурацями, состояниями объектов, взаимосвязями, используют их функции и т.п. Edd.DragonПочему мы только на "третий день" узнаем, что дело не в автоподтирании, а в том, что у вас какие-то проблемы с инкапсуляцией и вы не хотите видеть ее в общепринятом виде? У меня нет проблем с инкапсуляцией!! все с ней отлично!! задача про автоподтирание более того, инкапсуляции-то нет, ведь указатель не хранится в объекте, а хранится глобально!! мы тут ничего не инкапсулируем. вся "инкапсуляция" происходит внутри функции b()!! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.12.2012, 22:15 |
|
||
|
Поймать факт перезаписи
|
|||
|---|---|---|---|
|
#18+
Lumix вся обсуждаемая тема про то, как изнутри объекта можно управлять всеми указателями, которые на этот объект ссылаются. Это вообще в корне неправильный подход. Управлять жизнью объекта должен не сам объект, а кто-то другой. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.12.2012, 22:26 |
|
||
|
Поймать факт перезаписи
|
|||
|---|---|---|---|
|
#18+
Lumixречь не идет об автоматическом удалении объектов в смысле автоматический поиск, потому что мы не знаем "где, когда и при каких обстоятельства мы потеряли ребенка". речь идет об автоматической зачистке, когда мы точно знаем в какой именно момент и при каком именно действии это происходит: в момент присвоения указателю нового адреса MasterZivЭто (garbage collector) должен реализовать какой-то другой класс, внешний по отношению к твоему. И логично это делать сразу для нескольких классов, а не для одного. тема не про GC Я опять ничего не понял, уж извини, и думаю, что не потому, что я тупой такой. Объект один, указателей на него много. Как ты при перезаписывании одного указателя собираешься уничтожать объект -- не понятно. А если это возможно, то всё, знаешь ли, очень просто -- сокрой все методы создания и удаления объекта в классе, сделай что-то типа фабрики, но ещё и с поддержкой удаления, -- и всё, делов-то. Только выглядеть это будет вовсе не так, как ты видимо хочеш, и совсем не по С++-овски. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.12.2012, 22:32 |
|
||
|
Поймать факт перезаписи
|
|||
|---|---|---|---|
|
#18+
MasterZivЭто вообще в корне неправильный подход. Управлять жизнью объекта должен не сам объект, а кто-то другой. Я и не настаиваю, что должен сам объект. На шарах вон решение уже есть. Осталось совсем чуть-чуть допилить юзерскую часть... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.12.2012, 22:35 |
|
||
|
Поймать факт перезаписи
|
|||
|---|---|---|---|
|
#18+
LumixmaytonКак мы можем это знать в рамках С++ ? Блин, вообще-то это я с этим вопросом сюда пришел. ))) Если бы я знал, темы бы не было... Родной, если бы ты это знал бы, или кто другой бы знал, то уже бы вся IT-индустрия была бы лет на 100 впереди. Для того, чтобы это сделать, надо иметь поддержку присваивания ссылок на уровне языка. Как в Java или C# или других языках с GC. А в С++ такого нет. Зато есть ПРОИЗВОЛЬНОЕ управление памятью программистом, чего нет в вышеупомянутых языках. Ты хочеш скрестить ужа с дикообразом ? И что получится ? И главное зачем ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.12.2012, 22:36 |
|
||
|
Поймать факт перезаписи
|
|||
|---|---|---|---|
|
#18+
MasterZivА если это возможно, то всё, знаешь ли, очень просто -- сокрой все методы создания и удаления объекта в классе, сделай что-то типа фабрики, но ещё и с поддержкой удаления, -- и всё, делов-то. Только выглядеть это будет вовсе не так, как ты видимо хочеш, и совсем не по С++-овски. Немного не понял идею про фабрику... Просто вот то решение, которое сейчас предложили на шарах, я разложил его на две части: сам класс class A + управляющая функция a(), которая при первом обращении к себе создает объекты, а при последующих просто возвращает уже созданный, при этом она дает доступ ко всем методам и дата-мемберам a()->draw(), a()->title = "Hello";, позволяет убивать себя как обычно delete a(), которая при этом убивает ещё и всех своих присоединенных чилдренов a()->addChild(b()) c()->setParent(a()) все это круто работает и теперь встала задача развить функционал чтобы можно было эти горячие объекты ещё и заменять новыми объектами, без нарушения участия этого объекта в других частях программы, чтобы можно было в любой части программы подменить b() = a() или что то же самое b() = new A, при этом все остальные части программы можно не трогать на самом деле все уже практически готово, потому что есть функционал b().reset(new A) или b().reset(a()) и остался совсем малюсенький шажок как это превратить в b() = new A ака b() = a(); ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.12.2012, 22:46 |
|
||
|
Поймать факт перезаписи
|
|||
|---|---|---|---|
|
#18+
Lumixя имел ввиду они не должны управлять ими в памяти А ключевое слово new кто пишет? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.12.2012, 22:47 |
|
||
|
Поймать факт перезаписи
|
|||
|---|---|---|---|
|
#18+
LumixMasterZivЭто вообще в корне неправильный подход. Управлять жизнью объекта должен не сам объект, а кто-то другой. Я и не настаиваю, что должен сам объект. На шарах вон решение уже есть. Осталось совсем чуть-чуть допилить юзерскую часть... Так у тебя будет всегда замкнутый круг. Если ты законтролируешь указатели на объекты в виде умных указателей, у тебя встанет проблема контролирования указателей на указатели (возможно, умные) на твои объекты. Законтролируешь этот уровень -- будет проблема со следующим. И так далее. Тебе для твоей задачи надо просто уйти от интерфейса в виде Код: plaintext 1. и всё будет проще. можно использовать хэндлы, номера объектов, имена объектов (на самом деле это всё одно и то же), что хочеш. И тебе сразу станет проще. Тебе нужно чтобы при перезаписи старое удалялось ? Напрямую реализуй эту концепцию в своём классе, сделай там слоты для объектов, и дай пользователям возможность в слотах создавать и удалять объекты. НЕ ДАВАЯ им доступ к объектам напрямую, инкапсулируя все операции с этими объектами по слотам. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.12.2012, 22:47 |
|
||
|
Поймать факт перезаписи
|
|||
|---|---|---|---|
|
#18+
Попробую потом написать код, как это примерно будет выглядеть.... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.12.2012, 22:48 |
|
||
|
Поймать факт перезаписи
|
|||
|---|---|---|---|
|
#18+
MasterZivДля того, чтобы это сделать, надо иметь поддержку присваивания ссылок на уровне языка. На самом деле я уже давно понял, что чистыми указателями эту задачу не решить, поэтому стал активно развивать тему с шарами, потому что они дают все те же самые плюшки, что и указатели, то есть можно забыть про границы функций и при этом они позволяют вешать крючки на события. В данном случае меня интересует событие operator=() MasterZivТы хочеш скрестить ужа с дикообразом ? И что получится ? И главное зачем ? GC я не строю. Это глупо. А задачу на лету потереть старый объект и на его место в памяти прошить новый объект это вполне реально. По сути дела, я спрятал все действия по работе с памятью за один интерфейс, которым в данном случае является функция аксессор a() то есть во всем коде, пользователь пишет как ему надо и использует функцию a(), а какие именно объекты, какие именно участки памяти там используются это управляется в другом месте, например, в контроллерах событий a() = b() ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.12.2012, 22:54 |
|
||
|
Поймать факт перезаписи
|
|||
|---|---|---|---|
|
#18+
Edd.DragonА ключевое слово new кто пишет? Функция аксессор при первом обращении. При любом первом обращении!! пользователь пишет Код: plaintext 1. 2. 3. удалил первую строчку Код: plaintext 1. 2. в общем, кто первый вызвал, тот и папа ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.12.2012, 22:56 |
|
||
|
Поймать факт перезаписи
|
|||
|---|---|---|---|
|
#18+
MasterZivЕсли ты законтролируешь указатели на объекты в виде умных указателей, у тебя встанет проблема контролирования указателей на указатели (возможно, умные) на твои объекты. Я немного не понял зачем share_ptr контроллировать??... Неужели есть случай, когда и на них образуются висяки?? ведь мы абсолютно все операции с ними спрятали под капот аксессоров... в пользовательском коде вообще нигде ни разу не должно всплыть share_ptr ни разу!! они вообще не должны знать что такое есть вообще!! MasterZivТебе для твоей задачи надо просто уйти от интерфейса в виде Код: plaintext 1. и всё будет проще. можно использовать хэндлы, номера объектов, имена объектов (на самом деле это всё одно и то же), что хочеш. И тебе сразу станет проще. А у нас такого и нет вообще. Это я просто для примера тут приводил. У нас вообще нет объектов в пользовательской части, только функции. Объекты только данных: строки, числа, картинки, кисти и т.п., т.е. вся расходка. Все остальное существует только в виде функций, т.е. все спрятано под капот. Глобальные номерки это все уже есть и все работает. То есть у каждого аксессора уже гарантировано есть a()->gloId, a()->className и другая мета, но я пока не придумал как это можно заюзать для решения задачи, обсуждаемой в этой ветке. MasterZivТебе нужно чтобы при перезаписи старое удалялось ? Напрямую реализуй эту концепцию в своём классе, сделай там слоты для объектов, и дай пользователям возможность в слотах создавать и удалять объекты. НЕ ДАВАЯ им доступ к объектам напрямую, инкапсулируя все операции с этими объектами по слотам. Немного не понял... Любой объект уже можно БЕЗОПАСНО удалить через delete a(); а любой последующий вызов a() создаст новый объект. Сейчас задача про a(1) = a(2), чтобы а(1) при этом потерся из памяти и записал на свое место a(2), чтобы они в итоге оба указывали на одно и то же. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.12.2012, 23:10 |
|
||
|
Поймать факт перезаписи
|
|||
|---|---|---|---|
|
#18+
MasterZivПопробую потом написать код, как это примерно будет выглядеть.... ok ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.12.2012, 23:12 |
|
||
|
Поймать факт перезаписи
|
|||
|---|---|---|---|
|
#18+
Lumix Код: plaintext 1. как теперь можно спрятать этот make_shared, чтобы остался только = new A Это требование бессмысленно. Не надо вообще работать с new и голыми указателями. Смартуказатель предоставляет АПИ для всех необходимых операций с указателем и объектом. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.12.2012, 23:59 |
|
||
|
|

start [/forum/topic.php?fid=57&msg=38076739&tid=2020561]: |
0ms |
get settings: |
10ms |
get forum list: |
14ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
47ms |
get topic data: |
13ms |
get forum data: |
3ms |
get page messages: |
59ms |
get tp. blocked users: |
1ms |
| others: | 266ms |
| total: | 421ms |

| 0 / 0 |
