Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Static member initialisation corrupted #751

Closed
ekkis opened this issue Nov 30, 2019 · 2 comments
Closed

Static member initialisation corrupted #751

ekkis opened this issue Nov 30, 2019 · 2 comments
Labels
invalid This doesn't seem right

Comments

@ekkis
Copy link

ekkis commented Nov 30, 2019

I've posted here as a question https://eosio.stackexchange.com/questions/5106/static-values-get-mangled, in case I'm just doing something badly but I think this is a bug with the compiler. I have the code below:

#include <eosio/eosio.hpp>
#include <eosio/asset.hpp>

namespace eosio {
    class UTL {
        public:
        static name code;
        static symbol sym;
    };  

    class [[eosio::contract("static")]] dapp : public contract {
        public:

        dapp(name receiver, name code, datastream<const char*> ds) 
            : eosio::contract(receiver, code, ds) {
            UTL::code = code;
            print("\nconstructor(I): code=", UTL::code);
            UTL::sym = symbol("XX", 2); 
            print("\nconstructor(II): code=", UTL::code);
        }   

        [[eosio::action]]
        void tst() {
            print("\ntst(): code=", UTL::code, ", sym=", UTL::sym);
        }   
    };  
}

from which it can be seen that as soon as the second initilisation occurs (UTL::sym), the value of the first one (UTL::code) gets messed up

this approach is very useful as it allows me to create static methods for things for which I don't really need to or want to instantiate an object. but the static methods need access to certain variables, which can easily be initialised during the contract constructor

however, this fails. here's typical output:

constructor(I): code=testacct
constructor(II): code=......2scp2.c,

from which it can be seen that the value of code becomes corrupt

I'm running on eosio v1.8.4. help?

@larryk85
Copy link
Contributor

larryk85 commented Dec 2, 2019

This is not a problem with CDT. Your program is using undefined behavior, and as such is doing something weird. You have to explicitly initialize those fields.

#include <eosio/eosio.hpp>
#include <eosio/asset.hpp>

using namespace eosio;
class UTL {
   public:
      static name code;
      static symbol sym;
};

// initialize the static fields
name UTL::code = name{};
symbol UTL::sym = symbol{};

class [[eosio::contract]] test : public contract {
   public:
      test(name r, name c, datastream<const char*> d) : contract(r,c,d) {
         UTL::code = c;
         print_f("code= %\n", UTL::code);
         UTL::sym = symbol("XX", 2);
         print_f("code= %, sym= %\n", UTL::code, UTL::sym);
      }

      [[eosio::action]]
      void tst() {
         print_f("tst() : code= %, sym= %\n", UTL::code, UTL::sym);
      }
};

Output of cleos push action eosio tst '[]' -p eosio without static initialization:

>> code= eosio
>> code= .........flg.2, sym= 2,XX
>> tst() : code= .........flg.2, sym= 2,XX

Output of cleos push action eosio tst '[]' -p eosio with the static initialization:

>> code= eosio
>> code= eosio, sym= 2,XX
>> tst() : code= eosio, sym= 2,XX

Let me know if you have any other questions. Thanks for bringing this up, I will add this to a list of C++ gotchas for smart contract developers.

@larryk85 larryk85 added the invalid This doesn't seem right label Dec 2, 2019
@ekkis
Copy link
Author

ekkis commented Dec 2, 2019

ah! you're entirely correct. thank you for this. my bad

@ekkis ekkis closed this as completed Dec 2, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
invalid This doesn't seem right
Projects
None yet
Development

No branches or pull requests

2 participants