¿Comportamiento inesperado con la palabra clave de almacenamiento?

¿Alguien podría explicarme qué sucede exactamente cuando declaro un puntero de almacenamiento?

Este ejemplo destaca el problema que he encontrado:

contract minimum {

  uint256[] a = [1,2,3,4];

  function createOffersAsList() public returns (uint256[]) {

    uint256[] storage b;
    uint256 i = 0;

    Logger("Before loop", b); 
    // What I expected it to return: '"Before loop", ""'
    // What it actually returns: '"Before loop", "1, 2, 3, 4"'
    
    while (i<4) {
        b.push(a[i]);
        i++;
    }
    Logger("After loop", b);
    return b;
    // What I expected it to return: '"After loop", "1, 2, 3, 4"'
    // What it actually returns: '"After loop", "1, 2, 3, 4, 1, 2, 3, 4"'
  }

  event Logger(string s, uint256[] u);
}

Me parece que cuando declaro b, se asigna automáticamente al almacenamiento de a. ¿Porqué es eso? ¿Hubiera pensado que solo está asignado a algún espacio libre?

Y si necesito usar una matriz local de tamaño dinámico, ¿cómo se vería esto?

Gracias de antemano y un saludo, carbee

Respuestas (1)

Cuando declara una variable de almacenamiento, es esencialmente una referencia a alguna ubicación en el almacenamiento. Hasta que lo asigne a algo, apunta a la ubicación 0, que también es la ubicación de la primera variable de estado declarada (en este caso a). Básicamente estás usando un puntero no inicializado.

Consulte http://solidity.readthedocs.io/en/develop/types.html#data-location .

Para su segunda pregunta, puede asignar matrices de longitud variable en la memoria usando la newpalabra clave, pero no puede cambiar su tamaño después de la creación.

Consulte http://solidity.readthedocs.io/en/develop/types.html#allocating-memory-arrays .

¡Muchas gracias, eso tiene sentido! ¿Hay alguna manera de inicializar el puntero a otra ubicación de almacenamiento que aún no contiene valores?
¿Cómo volvería a encontrar ese almacenamiento más tarde? Podrías usar una mappingmatriz o.
Supongo que el almacenamiento se caracteriza por la ubicación (por ejemplo, 0) y no por el valor que contiene.
Me refiero, por ejemplo, a declarar una matriz como una variable de estado, y luego en su función, .push(...)extenderla y usar el nuevo elemento.