Menu

Err: Mult def of static obj.

2008-09-28
2012-09-26
  • Richard Kopcke

    Richard Kopcke - 2008-09-28

    I am running Dev-C++ 4.9.9.2 with XP.
    I am obtaining a multiple def build error for a private static object. This obj is only declared in the mySeq.hpp file, once in the private section of the class's scope and once after the class's scope. (Omitting this definition outside the scope produces the expected error.)

    In addition to this error I have a related question. I assume it good practice to add to the class a means of releasing the storage on the heap created by the class's private static objects. If so, would using the setDefault member to delete the data and set the object's pointer to NULL be a good idea? Or, is it considered better to add another static member that deletes the static object's data and sets the pointer to NULL?

    Thank you,
    Dick

    Compiler: Default compiler
    Building Makefile: "C:\CPP\test\Makefile.win"
    Executing make...
    make.exe -f "C:\CPP\test\Makefile.win" all
    g++.exe -c mySeq.cpp -o mySeq.o -I"C:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include" -I"C:/Dev-Cpp/include/c++/3.4.2/backward" -I"C:/Dev-Cpp/include/c++/3.4.2/mingw32" -I"C:/Dev-Cpp/include/c++/3.4.2" -I"C:/Dev-Cpp/include"

    g++.exe testStatic.o mySeq.o -o "testStatic.exe" -L"C:/Dev-Cpp/lib"

    mySeq.o(.bss+0x0):mySeq.cpp: multiple definition of `mySeq::defaultSeq'
    testStatic.o(.bss+0x0):testStatic.cpp: first defined here
    collect2: ld returned 1 exit status

    make.exe: *** [testStatic.exe] Error 1

    Execution terminated

    ifndef MYSEQ_HPP

    define MYSEQ_HPP

    class mySeq
    {
    public:
    mySeq(const int n=0, const double* const d=0);
    ~mySeq() { delete [] data; data = 0; }

       void writeSeq() const;
    
       static void setDefault(const int=0, const double* const d=0);
       static void writeDefault() { defaultSeq.writeSeq(); }
    

    private:
    int size;
    double* data;
    static mySeq defaultSeq;
    };

    mySeq mySeq::defaultSeq;

    endif

    include <cstdlib>

    include <iostream>

    include <cmath>

    include "mySeq.hpp"

    mySeq::mySeq(const int n, const double* const d)
    {
    size = n ? n : defaultSeq.size;
    if ( size>0 )
    {
    data = new double [size];
    if (n==0)
    {
    for (int i=0; i<size; i++) data[i] = defaultSeq.data[i];
    }
    else
    {
    for (int i=0; i<size; i++) data[i] = d[i];
    }
    }
    else data = 0;
    }

    void mySeq::setDefault(const int sz, const double* const d)
    {
    defaultSeq.size = sz;
    if (defaultSeq.data != 0)
    {
    delete[] defaultSeq.data;
    defaultSeq.data = 0;
    }
    if (sz>0)
    {
    defaultSeq.data = new double [sz];
    for (int i=0; i<sz; i++) defaultSeq.data[i]=d[i];
    }
    }

    void mySeq::writeSeq() const
    {
    if (size>0)
    {
    for (int i=0; i<size; i++)
    {
    std::cout << i << '\t' << data[i] << '\n';
    }
    }
    std::cout << '\n';
    }

    include <cstdlib>

    include <iostream>

    include <cmath>

    include "mySeq.hpp"

    int main(int argc, char *argv[])
    {
    int ndefault=3;
    double d[] = {1., 1., 1.};

    mySeq::setDefault(ndefault, d);
    
    std::cout &lt;&lt; &quot;defaultList&quot; &lt;&lt; '\n' &lt;&lt; '\n';
    mySeq::writeDefault();
    
    system(&quot;PAUSE&quot;);
    return EXIT_SUCCESS;
    

    }

     
    • Anonymous

      Anonymous - 2008-09-29

      In relation with your's first question, IMHO you can not declare that static member.

      static mySeq defaultSeq;

      Here defaultSeq is a mySeg objetc type, and there are a circular definition; mySeg class is defined inside the definition. You can use a pointer to mySeg there but not mySeg itself.

      HTH.

       
    • cpns

      cpns - 2008-09-29

      By placing teh declaration:

      mySeq mySeq::defaultSeq;

      In the header file, you create an instance of mySeq::defaultSeq in every module that includes the header, so the linker sees more than one. That line should be moved to MySeq.cpp so there is only one instance.

      Clifford

       
      • Richard Kopcke

        Richard Kopcke - 2008-09-29

        I tried moving this statement as you suggested. The results (see below) produced a similar error. I have written "self referential" declarations and definitions successfully before. And, this program does run well if all modules are placed in one .cpp file.

        Compiler: Default compiler
        Building Makefile: "C:\CPP\test\Makefile.win"
        Executing make...
        make.exe -f "C:\CPP\test\Makefile.win" all
        g++.exe testStatic.o mySeq.o -o "testStatic.exe" -L"C:/Dev-Cpp/lib"

        mySeq.o(.bss+0x0):mySeq.cpp: multiple definition of `mySeq::defaultSeq'
        testStatic.o(.bss+0x0):testStatic.cpp: first defined here
        collect2: ld returned 1 exit status

        make.exe: *** [testStatic.exe] Error 1

        Execution terminated

        ifndef MYSEQ_HPP

        define MYSEQ_HPP

        class mySeq
        {
        public:
        mySeq(const int n=0, const double* const d=0);
        ~mySeq() { delete [] data; data = 0; }
        mySeq(const mySeq&);
        mySeq& operator=(const mySeq&);

           void writeSeq() const;
        
           static void setDefault(const int=0, const double* const d=0);
           static void writeDefault() { defaultSeq.writeSeq(); }
        

        private:
        int size;
        double* data;
        static mySeq defaultSeq;
        };

        endif

        include <cstdlib>

        include <iostream>

        include <cmath>

        include "mySeq.hpp"

        mySeq mySeq::defaultSeq;

        mySeq::mySeq(const int n, const double* const d)
        {
        size = n ? n : defaultSeq.size;
        if ( size>0 )
        {
        data = new double [size];
        if (n==0)
        {
        for (int i=0; i<size; i++) data[i] = defaultSeq.data[i];
        }
        else
        {
        for (int i=0; i<size; i++) data[i] = d[i];
        }
        }
        else data = 0;
        }

        mySeq::mySeq(const mySeq& v)
        {
        data = new double [size=v.size];
        for (int i=0; i<v.size; i++) data[i] = v.data[i];
        }

        mySeq& mySeq::operator=(const mySeq& v)
        {
        if (this != &v) //if addr of lhs = addr of rhs, then do nothing
        { //cannot use for static obj, has no this pointer
        if (size != v.size)
        {
        delete [] data;
        data = 0;
        data = new double [size=v.size];
        }
        for (int i=0; i<v.size; i++) data[i]=v.data[i];
        }
        return *this;
        }

        void mySeq::setDefault(const int sz, const double* const d)
        {
        defaultSeq.size = sz;
        if (defaultSeq.data != 0)
        {
        delete[] defaultSeq.data;
        defaultSeq.data = 0;
        }
        if (sz>0)
        {
        defaultSeq.data = new double [sz];
        for (int i=0; i<sz; i++) defaultSeq.data[i]=d[i];
        }
        }

        void mySeq::writeSeq() const
        {
        if (size>0)
        {
        for (int i=0; i<size; i++)
        {
        std::cout << i << '\t' << data[i] << '\n';
        }
        }
        std::cout << '\n';
        }

        include <cstdlib>

        include <iostream>

        include <cmath>

        include "mySeq.hpp"

        int main(int argc, char *argv[])
        {
        int ndefault=3;
        double d[] = {1., 1., 1.};

        mySeq::setDefault(ndefault, d);
        
        std::cout &lt;&lt; &quot;defaultList&quot; &lt;&lt; '\n' &lt;&lt; '\n';
        mySeq::writeDefault();
        
        system(&quot;PAUSE&quot;);
        return EXIT_SUCCESS;
        

        }

         
        • Anonymous

          Anonymous - 2008-09-29

          >> I have written "self referential" declarations and definitions successfully before.

          Would you show an easy example of that? I mean a self reference to the class, not a pointer to the class.

          Thanks in advance.

           
          • Richard Kopcke

            Richard Kopcke - 2008-09-30

            Clifford had the correct observation. So this current problem might meet your request. See the following .hpp for the class, .cpp for the class, and main.

            ifndef MYSEQ_HPP

            define MYSEQ_HPP

            class mySeq
            {
            public:
            mySeq(const int n=0, const double* const d=0);
            ~mySeq() { delete [] data; data = 0; }
            mySeq(const mySeq&);
            mySeq& operator=(const mySeq&);

               void writeSeq() const;
            
               static void setDefault(const int=0, const double* const d=0);
               static void writeDefault() { defaultSeq.writeSeq(); }
            

            private:
            int size;
            double* data;
            static mySeq defaultSeq;
            };

            endif

            include <cstdlib>

            include <iostream>

            include <cmath>

            include "mySeq.hpp"

            mySeq mySeq::defaultSeq;

            mySeq::mySeq(const int n, const double* const d)
            {
            size = n ? n : defaultSeq.size;
            if ( size>0 )
            {
            data = new double [size];
            if (n==0)
            {
            for (int i=0; i<size; i++) data[i] = defaultSeq.data[i];
            }
            else
            {
            for (int i=0; i<size; i++) data[i] = d[i];
            }
            }
            else data = 0;
            }

            mySeq::mySeq(const mySeq& v)
            {
            data = new double [size=v.size];
            for (int i=0; i<v.size; i++) data[i] = v.data[i];
            }

            mySeq& mySeq::operator=(const mySeq& v)
            {
            if (this != &v) //if addr of lhs = addr of rhs, then do nothing
            { //cannot use for static obj, has no this pointer
            if (size != v.size)
            {
            delete [] data;
            data = 0;
            data = new double [size=v.size];
            }
            for (int i=0; i<v.size; i++) data[i]=v.data[i];
            }
            return *this;
            }

            void mySeq::setDefault(const int sz, const double* const d)
            {
            defaultSeq.size = sz;
            if (defaultSeq.data != 0)
            {
            delete[] defaultSeq.data;
            defaultSeq.data = 0;
            }
            if (sz>0)
            {
            defaultSeq.data = new double [sz];
            for (int i=0; i<sz; i++) defaultSeq.data[i]=d[i];
            }
            }

            void mySeq::writeSeq() const
            {
            if (size>0)
            {
            for (int i=0; i<size; i++)
            {
            std::cout << i << '\t' << data[i] << '\n';
            }
            }
            std::cout << '\n';
            }

            include <cstdlib>

            include <iostream>

            include <cmath>

            include "mySeq.hpp"

            int main(int argc, char *argv[])
            {
            int ndefault=3;
            double d[] = {1., 1., 1.};

            mySeq::setDefault(ndefault, d);
            
            std::cout &lt;&lt; &quot;defaultList&quot; &lt;&lt; '\n' &lt;&lt; '\n';
            mySeq::writeDefault();
            
            system(&quot;PAUSE&quot;);
            return EXIT_SUCCESS;
            

            }

             
        • cpns

          cpns - 2008-09-29

          That log only shows the linker stage, so nothing was re-compiled, only a re-link of previously compiled modules. Although of course this may not have been your first build since the change. Do a "Rebuild All" before posting the log.

          My guess is in fact that you have incomplete file dependencies in the project makefile and that testStatic.cpp was never recompiled when MySeq.hpp changed, so it still contains the old static instance. If that is the case, the Rebuild All will solve the problem, but you should switch off Dev-C++'s "Fast but imperfect dependency generation" mode - it does not work, and besides that on a small project, complete dependencies do not take long to generate, and on a large project that are essential.

          It would be useful when posting multiple source file content if you could put some sort of separator between them!

          Clifford

           
          • Richard Kopcke

            Richard Kopcke - 2008-09-30

            Right you are. It works fine now. Someday I just might get the hang of this IDE. I appreciate you patience.

            Dick

             

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.