chronos-tachyon / googletest-bazel

Fork of googletest that uses bazel.build
https://github.com/google/googletest
BSD 3-Clause "New" or "Revised" License
4 stars 4 forks source link

Application crashed due to no guarantee of the initialization order of global instances between gmock and programm #461

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
This phenomenon can appear repeatedly if our program is linked with gmock/gtest 
object files. However the crash is gone if we link our program with gmock/gtest 
static libraries.
Steps:
1. Compile all the source codes including gmock/gtest source.
2. link all the object files as a single executable.
3. Run this program with options --gtest_output --gtest_filter
We check the coredump file and find the program crashed just before the main 
function with signal segment fault - invalid access to 
g_uninteresting_call_reaction. This variable is defined in gmock as a global 
variable.
Here I summary why this happens:
Our program defines some global variables such as: NiceMock<Something> 
something.
The template class NiceMock's constructor accesses the global variable 
g_uninteresting_call_reaction. These 2 variables locate in different 
translation units and the compiler has no guarantee of the initialization order 
of global instances between different translation units. 
Could you please provide solution for this? For example, add #pragma init_seg
preprocessor directive for some global variables?
Platform: Linux 2.6.32-358.23.2.el6.x86_64 #1 SMP Wed Oct 16 18:37:12 UTC 2013 
x86_64 x86_64 x86_64 GNU/Linux
gmock/gtest: 1.7.0
compiler: GNU g++ 4.7.4

Original issue reported on code.google.com by threepea...@gmail.com on 23 May 2014 at 8:52

GoogleCodeExporter commented 9 years ago
I can reproduce the same issue with compiler GNU g++ 4.7.3:  
Here's code that can reproduce the issue:

#include "gmock/gmock.h"
#include "gtest/gtest.h"

using testing::NiceMock;

class Foo {
  public:
  virtual ~Foo() {}

  virtual void DoThis() = 0;
  virtual int DoThat(bool flag) = 0;
};

class FooMock : public Foo {
  public:
    FooMock() {}

    MOCK_METHOD0(DoThis, void());
    MOCK_METHOD1(DoThat, int(bool flag));
};

// If uncommented, g++ 4.6.3+ will crash before main() is called
// NiceMock<FooMock> *g_mockFoo = new NiceMock<FooMock>;

// If uncommected, g++ 4.6.3+ will crash before main() is called
// NiceMock<FooMock> g_mockFoo2;

TEST(NiceMockTest, ThisTestPasses)
{
    NiceMock<FooMock> mockFoo;  // Does not cause crash
    mockFoo.DoThis();
    mockFoo.DoThat(true);
}

Original comment by Gramanda...@gmail.com on 5 Sep 2014 at 2:12

GoogleCodeExporter commented 9 years ago
I should elaborate why this is important to me...  If I have a "C" interface 
that I want to mock, to translate between c and c++ gmock library, I do this:

myfile.c
--------
void add1() { Best_Add1(); }
void sub1() { Best_Sub1(); }

myMock.cpp
----------
class MockBest {
  public:
    MOCK_METHOD0(Add1, void());
    MOCK_METHOD0(Sub1, void());
};

NiceMock<MockBest> bestMock;

extern "C" {
   Better_Add1(){
      bestMock.Add1();
   }

   Better_Sub1(){
      bestMock.Sub1();
   }
};

Without NiceMock, this design works perfectly well, however, when adding in 
NiceMock, I get the above crash which is preventing me from testing "C" 
interfaces with GoogleMock library (unless I want to see thousands of warnings) 
;-). Please help evaluate a workaround, and possibly increase the priority of 
this fix.

Original comment by Gramanda...@gmail.com on 5 Sep 2014 at 2:25

GoogleCodeExporter commented 9 years ago
I'll try making the g_uninteresting_call_reaction map a lazily-initialized 
object accessible only through an accessor function. But I really think you 
should do the same with your bestMock. Then you probably wouldn't have this 
problem.

class MockBest {
  public:
    MOCK_METHOD0(Add1, void());
    MOCK_METHOD0(Sub1, void());
};

MockBest& GetMockBest() {
  static NiceMock<MockBest> v = NiceMock<MockBest>();
  return v;
}

extern "C" {
   Better_Add1(){
      GetMockBest().Add1();
   }

   Better_Sub1(){
      GetMockBest().Sub1();
   }
};

Original comment by billydon...@google.com on 6 Sep 2014 at 6:30