Solc-Compiler-Aufsicht? Ungeeignete Mapping-Deklaration überschreibt Speicher

Ich habe einen Vertrag geschrieben, der die Zuordnungsspeichervariablen A & B enthält. Diese Variablen werden mit einigen Werten im Konstruktor initialisiert. Eine Methode getBalance gibt den Kontostand von Mapping A & B zurück.

In der Methode habe ich eine andere Zuordnung deklariert - ich dachte, dass dies zu einem Kompilierungsfehler führen würde (da die Zuordnung nur für die Speicherung zulässig ist). Stattdessen führte es zu einem seltsamen Verhalten - es scheint, dass die neue lokale Zuordnung die Zuordnung A überschreibt.

Ergebnis ohne lokales Mapping (100, 200) wie erwartet Ergebnis mit lokalem Mapping (500, 200) <<< Warum?

/** Getestet in Truffle/TestRPC **/

contract Mapping {

  mapping(address => uint)  balancesA;
  mapping(address => uint)  balancesB;

  function Mapping() {
    // constructor
    balancesA[msg.sender] = 100;
    balancesB[msg.sender] = 200;
  }

  function getBalance(address addr) returns(uint, uint) {

    // If these 2 lines are commented then behavior is as expected
    mapping(address => uint)  balancers;
    balancers[msg.sender] = 500;

    return (balancesA[addr], balancesB[addr]);

  }
}
Das kann ich bestätigen. Die Zuordnung in der Funktion scheint mit der ersten ordnungsgemäß deklarierten Zuordnung zu kollidieren.
Haben Sie versucht, es auf Testnet (oder privatem Netzwerk) auszuführen? Manchmal verhält sich TestRPC anders als ein "echtes" Netzwerk - vielleicht ist das der Fall.
Ich kann auch in Geth reproduzieren.
Ein weiterer interessanter .... wenn ich die Reihenfolge der Deklaration ändere ... deklariere balancesB vor balancesA ..... dann kollidiert es mit balancesB, so dass die erste 1 überschrieben wird, dh das Ergebnis ist (100 500)
@ACloudFan Es sieht so aus, als wäre es Zeit für Fehlerberichte. Willst du die Ehre erweisen?
Fehler beiseite, die Rückgabeparameter werden nicht korrekt verwendet. Sollte returns (uint, uint)eher als genannt werden, oder balanceA = balancesA[addr];etc

Antworten (3)

Habe hier ein Issue eröffnet, github, ethereum, solidity, issue 1731: https://github.com/ethereum/solidity/issues/1731

Wenn ich ihren Prozess richtig verstehe, wird die ursprüngliche Ausgabe 1731 durch Ausgabe 1737 geschlossen, die jetzt zusammengeführt wird. Möglicherweise gibt der Compiler in Zukunft einen Fehler für solche Dinge aus.

Beide Daumen hoch für die Entwickler!

https://github.com/ethereum/solidity/pull/1737

Abgesehen davon ist es ein Fehler in der Solidität (da es bemerken sollte, dass eine nicht initialisierte Variable verwendet wird), es ist erwähnenswert, dass der Code auch nicht korrekt ist.

Das Problem ist, dass mapping(address => uint) balancersim Funktionskörper keine neue Zuordnung zugewiesen wird. Es führt nur eine Variable ein balancers, die auf eine (an anderer Stelle zugewiesene) Zuordnung verweisen kann.

Im Beispiel balancerswird nicht initialisiert und zufällig referenziert balancesA. Daher das unerwartete Verhalten.

Aus Solidity-Dokumenten :

Zuordnungen sind nur für Zustandsvariablen (oder als Speicherreferenztypen in internen Funktionen) zulässig.

Ich fürchte, das ist kein Bug. Ich stimme sehr zu, dass es ein Problem ist und eine riesige Falle darstellt.

Bitte sehen Sie sich die Dokumentation hier an: https://solidity.readthedocs.io/en/v0.4.9/types.html#data-location

Wie in der Antwort von Max Taldykin erwähnt: Indem Sie die lokalen Variablenbalancer innerhalb der Funktion deklarieren, erstellen Sie lediglich eine neue Referenz mit einem anderen Namen, die auf eine Zuordnung im Speicher verweist. Ich schätze, es verlinkt nur auf das erste, das es auf globaler Ebene deklariert findet.

Das Deklarieren der lokalen Variablen als Speicher würde das Überschreiben verhindern.

mapping(address => uint) memory balancers;

Um es klar zu sagen: Dieses Problem gilt nur für Nicht-Primitive (Strukturen, Zuordnungen und Arrays), wenn sie lokal innerhalb von Funktionen deklariert werden, da ihr Standardspeicherort der Speicher ist , wie in dem oben verlinkten Dokument erläutert!

Der Fehler ist, dass der Compiler nicht vor der Verwendung nicht initialisierter Variablen warnt.
Vielen Dank. Interessant und beängstigend. Vielleicht kein "Fehler", aber nicht hilfreich oder gewollt in einer unversöhnlichen Umgebung. In etwa so: vessenes.com/solidity-frustrations-references-and-mapping reference vars und seltsame Mapping-Überschneidungen; Ich mag sie nicht Sam I Am.
@maxtaldykin Scheint, als ob die Compiler-Leute Ihnen zustimmen. Sie haben Problem 1737 (1731) zu dem von mir gemeldeten Problem hinzugefügt und scheinen daran zu arbeiten. github.com/ethereum/solidity/pull/1737