API-интерфейс Swift JSON (SwiftyJSON) [закрыто]

Это, конечно, не совсем корректное поведение в целом.

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

Более конкретно, объект был просто удален этим очень ничто, поэтому маловероятно, чтобы какой-либо поток действительно обходил его использование между удалением и чтением / записью, или он был неотображаем, поэтому вряд ли это действительно вызовет проблемы в простой программе. Кроме того, существует небольшая очевидная причина для реализации, чтобы читать или записывать в this после ее возвращения.

Однако Valgrind вполне корректен, что любое такое чтение или запись будет очень недействительный и в некоторых случаях может привести к случайным сбоям или повреждению памяти. Легко предположить, что между удалением this и гипотетическим чтением / записью этот поток был предварительно упущен, а другой поток назначен и использовал эту память. В качестве альтернативы, распределитель памяти решил, что у него достаточно кэшированной памяти такого размера, и сразу же освободил этот сегмент для ОС. Это отличный кандидат на Гейзенбуг, поскольку условия его возникновения будут относительно редкими и очевидны только в реальных сложных системах исполнения, а не в тривиальных тестовых программах.

Вы могли бы избежать этого , если вы можете доказать, что чтения или записи нет после завершения объекта функции. Это в основном означает гарантию реализации std::function<Sig>::operator().

Редактировать:

Ответ Матса Петерсона вызывает интересный вопрос. GCC, похоже, реализовал лямбда, выполнив что-то вроде этого:

struct lambda { std::function<void()>* f; };
void lambda_operator(lambda* l) {
    l->f->~std::function<void()>();
    ::operator delete(l->f);
}

Как вы можете видеть, вызов operator delete выполняет загрузку с l после того, как он только что был удален, что точно описанный выше сценарий. Я на самом деле не уверен, что правила модели памяти C ++ 11 говорят об этом, я бы подумал, что это незаконно, но не обязательно. Он не может быть определен в любом случае. Если это не является незаконным, вы определенно ввернуты.

Тем не менее Clang, похоже, сгенерирует этот оператор:

void lambda_operator(lambda* l) {
    auto f = l->f;
    f->~std::function<void()>();
    ::operator delete(f);
}

Здесь, когда l удален, это не имеет значения потому что f был скопирован в локальное хранилище.

В определенной степени это окончательно отвечает на ваш вопрос. GCC абсолютно загружает из памяти лямбда после ее удаления. Является ли это стандартным или нет, я не уверен. Вы определенно можете обойти это, используя определенную пользователем функцию. Тем не менее, проблема с реализацией std :: function, выполняющей загрузку или сохранение в хранилище до this.

-4
задан Guilherme Alexandre Fischer 16 January 2019 в 18:21
поделиться

1 ответ

Это на самом деле очень просто. Сначала определите структуру для вашего элемента словаря, например, так:

struct Item: Codable {
    let cd_sala: String
    let nm_sala: String
}

Затем создайте экземпляр для JSONDecoder:

let decoder = JSONDecoder()

и используйте его для декодирования данных

[112 ]

Dictionary<Int, Item> относится к классу хеш-таблицы по умолчанию (ключ, значение), который дает вам доступ к элементу, например:

// outputs "Treinamento de Teste"
print(object[1]!.nm_sala) 
0
ответ дан SmartArray 16 January 2019 в 18:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: