Что именно делает ключевое слово «память»?

Я просматривал код Etherdice и заметил, что некоторые переменные объявлены как

ParserResult memory result;

и я не нашел ключевого слова «память» ни в одной документации. То, что я нашел здесь, было следующим объяснением :

Они аналогичны памяти и жесткому диску компьютера. Контракт может использовать любой объем памяти (конечно, если он может за это заплатить) во время выполнения своего кода, но когда выполнение останавливается, все содержимое памяти стирается, и следующее выполнение начинается заново. С другой стороны, хранилище сохраняется в самой цепочке блоков, поэтому в следующий раз, когда контракт выполняет некоторый код, он также получает доступ ко всем данным, которые он ранее хранил в своей области хранения.

Действительно ли объявление «памяти» сохраняет значение в «памяти»? Разве не все локальные переменные внутри функции хранятся только в памяти, а глобальные переменные всегда хранятся в блокчейне? И какое здесь отношение к этому объяснению «памяти» ?

Ответы (1)

Настоятельно рекомендуется прочитать FAQ Solidity по «памяти» полностью, а фрагмент приведен ниже.

Виртуальная машина Ethereum имеет три области, в которых она может хранить предметы.

Первый — это «хранилище», где находятся все переменные состояния контракта. У каждого контракта есть собственное хранилище, оно постоянно между вызовами функций и довольно дорогое в использовании.

Второй — «память», она используется для хранения временных значений. Он стирается между (внешними) вызовами функций и дешевле в использовании.

Третий — это стек, который используется для хранения небольших локальных переменных. Его почти можно использовать бесплатно, но он может содержать только ограниченное количество значений.

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

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

Существуют значения по умолчанию для места хранения в зависимости от того, к какому типу переменной оно относится ( источник ):

state variables are always in storage
function arguments are always in memory
local variables of struct, array or mapping type reference storage by default
local variables of value type (i.e. neither array, nor struct nor mapping) are stored in the stack

В FAQ есть примеры кода, которые помогут объяснить дальше.

Распространенная ошибка — объявлять локальную переменную (структуры, массива или отображения) и предполагать, что она будет создана в памяти, хотя она будет создана в хранилище.

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

Огромное спасибо! Я клянусь, что поиск на их странице документов вчера не вел себя.
Нет проблем, это фундаментальная, но очень важная тема, так что хорошо, что вы спросили!
@eth Прошло много времени, но ... я вижу, что могу объявлять локальные переменные, например, uintбез местоположения данных. Я понимаю, что это требуется для массивов/сопоставлений/структур (как указано в документах + ваш ответ), но почему код жалуется на string?
@Ancinek помогает ethereum.stackexchange.com/questions/28333/… ? Я не отслеживал много изменений в Solidity, но в целом он следовал тенденции быть более явным, чем неявным.
@eth Спасибо за ответ! На самом деле я задал вопрос на SO ( stackoverflow.com/questions/70833745/… ), и после копания я нашел статью, объясняющую строки в Solidity ( coders-errand.com/working-with-strings-in-solidity ) – они в основном являются массивами, поэтому имеет смысл явно добавлять memoryих при игре с ними, например, внутри функций :)