compiler order with gcc 4.8.5 - gcc

My gcc version is 4.8.5
posix gcc version 4.8.5 20150623 (Red Hat 4.8.5-4) (GCC)
I have two cpp files:
1.cpp and 2.cpp
while there is a static function in 1.cpp called by 2.cpp。
In most machine,we should like this:
g++ 2.cpp 1.cpp
or it will cause compile error or runtime error。
However,in my machine with gcc 4.8.5,I must compile using “g++ 1.cpp 2.cpp” to make it run successful。
Is this the property of gcc4.8.5? or there is something wrong on my soft,or I used it wrong?
==============================================================
My machine is centos7 installed on virtulbox of mac. Here is my code:
1.h
#include <map>
using namespace std;
class A {
private:
A();
static A _instance;
map<int, int> test_map;
public:
static A& get_instance();
static void fun();
};
1.cpp
#include <iostream>
#include "1.h"
using namespace std;
A A::_instance;
A::A() {
cout << "A::A()\n";
}
A& A::get_instance() {
cout << "A::get_instance()\n";
return A::_instance;
// static A instance;
// return instance;
}
void A::fun() {
cout << "A::fun()\n";
get_instance().test_map[1];
}
main.cpp
#include <iostream>
#include "1.h"
using namespace std;
int test() {
cout << "test()\n";
A::fun();
return 0;
}
int y = test();
int main() {
cout << "main()\n";
A::fun();
}
In most machine and in what I see in the web, we should compile like this:
g++ main.cpp 1.cpp
But in my machine, I must compile like this:
g++ 1.cpp main.cpp
what's wrong with my machine or my gcc?

I think you are facing the static initialization order fiasco which is a classical C++ bug. If initialization function test() in main.cpp is called before constructor for A::_instance has been called, your code will access uninitialized A::_instance::test_map field which is likely to cause segmentation fault. I suggest you rewrite getInstance to create instance when needed:
A *A::_instance;
A& A::get_instance() {
cout << "A::get_instance()\n";
if(!_instance)
_instance = new A;
return *A::_instance;
}
As a side note, I suggest you to use AddressSanitizer to autodetect this and similar types of errors.

Related

Spinlock code using atomic_flag in C++ is not compiling in Mac

I tried to write a simple Spinlock code in C++ but the code is not getting compiled in the Mac but is compiling on other gcc compilers.
#include<iostream>
#include<thread>
#include<atomic>
using namespace std;
class SpinLock
{
public:
atomic_flag flag;
SpinLock() : flag(ATOMIC_FLAG_INIT) {}
void lock()
{
while(flag.test_and_set());
}
void unlock()
{
flag.clear();
}
};
SpinLock spin;
void critical_section()
{
spin.lock();
for(int i = 0 ; i < 10 ; i++)
{
cout << i << " ";
}
cout << endl;
spin.unlock();
}
int main()
{
thread t1(critical_section);
thread t2(critical_section);
t1.join();
t2.join();
}
I tried checking version of clang installed in my machine at the version is:
Apple clang version 13.1.6 (clang-1316.0.21.2)
Target: arm64-apple-darwin21.4.0
Thread model: posix
Can any one help me in the fact that why code is not getting compiled?
atomic_flag (const atomic_flag&T) is a deleted constructor, and STL defines only two constructors for the atomic_flag (another one is default).
ATOMIC_FLAG_INIT usually doesn't even refer to a value to feed the constructor with, it's just a macro to call some kind of default initialization (for MSVC it's defined as curly brackets {}). You may want to initialize your flag like this:
class SpinLock
{
public:
atomic_flag flag = ATOMIC_FLAG_INIT;
SpinLock() {}
...

SparseMatrix kroneckerProduct crashing

I'm compiling the following against eigen 3.3.5:
#include <Eigen/Dense>
#include <Eigen/Sparse>
#include <unsupported/Eigen/KroneckerProduct>
template <typename eT, int SIDE>
inline
auto
xLeft(const Eigen::Matrix<eT, SIDE, SIDE> & M)
{
Eigen::SparseMatrix<double> Id(SIDE, SIDE);
Id.setIdentity();
return kroneckerProduct(M.transpose(), Id);
}
void fail()
{
Eigen::Matrix<double,2,2> M = Eigen::Matrix<double,2,2>::Random();
std::cout << "die:" << xLeft(M) << "\n";
}
int main() { fail(); return 0; }
and getting a crash, anyone else see this, is this an Eigen bug or am I doing something wrong that I just can't see?
also:
g++ (GCC) 7.3.1 20180712 (Red Hat 7.3.1-6)

g++ compiler optimization: cannot convert ‘<brace-enclosed initializer list>’

Following code not compiling:
A.h
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
namespace net {
using Ip = in_addr_t;
using Port = in_port_t;
using SockFd = int;
class Params final {
public:
Ip getIp() const { return ip_; }
Port getPort() const { return port_; }
private:
Ip ip_ {INADDR_ANY};
Port port_ {htons(5)};
};
}
A.cpp
#include <iostream>
#include "A.h"
int main(){
net::Params a {};
std::cout << "Ip=" << a.getIp() << ", Port=" << a.getPort() << std::endl;
return 0;
}
Compilation:
g++-6 -O2 -std=c++11 A.cpp
Error:
In file included from /usr/include/x86_64-linux-gnu/bits/byteswap.h:35:0,
from /usr/include/endian.h:60,
from /usr/include/ctype.h:39,
from /usr/include/c++/6/cctype:42,
from /usr/include/c++/6/bits/localefwd.h:42,
from /usr/include/c++/6/ios:41,
from /usr/include/c++/6/ostream:38,
from /usr/include/c++/6/iostream:39,
from A.cpp:1:
A.h:21:15: error: statement-expressions are not allowed outside functions nor in template-argument lists
Port port_ {htons(5)};
^
In file included from A.cpp:3:0:
A.h:21:23: error: cannot convert ‘<brace-enclosed initializer list>’ to ‘net::Port {aka short unsigned int}’ in initialization
Port port_ {htons(5)};
^
But when I change port_ member variable initialization to: Port port_ {5};, g++ with -O2 compiles fine.
Above code compiles fine without optimization flag, whether port_ initialized as: Port port_ {htons(5)}; or as Port port_ {5};
Whats wrong?
Seems to be a ompiler and/or libstd bug. The compiler tries to optimize away the function call to htons with some macros and compiler magic. That results in some problem I do not understand. But you can define an inline function myhtons that calls htons and use that instead. Works for me with gcc 7.2.
inline Port myhtons( Port v )
{
return htons(v);
}
class Params final {
public:
Ip getIp() const { return ip_; }
Port getPort() const { return port_; }
private:
Ip ip_ {INADDR_ANY};
Port port_ { myhtons(5) };
};

Compiling C++.11 using g++ with error does not name a type

I'm struggling with g++ compilation over c++.11
Here is the problem I'm facing:
error: 'IGameController' does not name a type.
The IGameController is actually my class interface, where I've put the location on my g++ script.
Here it is my g++ script to compile:
cd C:\MinGW\bin\
g++ -std=c++11 -c c:\Users\me\Downloads\TheGame\TheGame.cpp
g++ -std=c++11 -Ic:\Users\me\Downloads\TheGame\GameController\inc -Ic:\Users\me\Downloads\TheGame\GameController\src -c c:\Users\me\Downloads\TheGame\GameController\src\GameController.cpp
g++ -std=c++11 -o c:\Users\me\Downloads\TheGame\TheGame.exe *.o
I don't understand why the script doesn't find my header files...
My project is structured like this:
TheGame\TheGame.cpp
TheGame\GameController\inc\GameControllerProvider.hpp
TheGame\GameController\inc\IGameController.hpp
TheGame\GameController\src\GameController.cpp
TheGame\GameController\src\GameController.hpp
Here is my source code:
[TheGame.cpp]
#include <iostream>
#include "GameController/inc/GameControllerProvider.hpp"
#include "GameController/inc/IGameController.hpp"
int main()
{
GameController::IGameController& gameController = GameController::GameControllerProvider::getGameController();
gameController.printSomething();
return 0;
}
[IGameController.hpp]
#pragma once
namespace GameController
{
class IGameController
{
public:
virtual void printSomething() = 0;
protected:
IGameController() {}
virtual ~IGameController() {}
};
}
[GameControllerProvider.hpp]
#pragma once
namespace GameController { class IGameController; }
namespace GameController
{
namespace GameControllerProvider
{
IGameController& getGameController();
}
}
[GameController.hpp]
#pragma once
#include "GameController/inc/IGameController.hpp"
namespace GameController
{
class GameController : public IGameController
{
public:
GameController();
virtual ~GameController();
void printSomething() override;
private:
};
}
[GameController.cpp]
#include <iostream>
#include "GameController/inc/IGameController.hpp"
#include "GameController/src/GameController.hpp"
#include "GameController/inc/GameControllerProvider.hpp"
namespace GameController
{
GameController::GameController() {}
GameController::~GameController(){}
void GameController::printSomething()
{
std::cout << "printSomething()" << std::endl;
}
}
// Provider
IGameController& GameControllerProvider::getGameController()
{
static GameController sGameController;
return sGameController;
}
}
I'm not familiar with namespaces, but for sure one of your problems is with the #include statements, where you give a wrong path to some files.
For instance, when you call IGameController.hpp (in inc/) from GameController.cpp (in src/), since you are using quoations marks (" "), you should give the full path to the file, and it should be written as:
#include "../inc/IGameController.hpp"
Hope it helps.

How can I remove the warning that my iterator has a non-virtual destructor when extending boost::iterator_facade?

When compiling with -Weffc++ and extending boost::iterator_facade, I get the compiler warning: base class has a non-virtual destructor. What can I do to fix this?
Here is sample code:
#include <iostream>
#include <boost/iterator/iterator_facade.hpp>
struct my_struct_t {
int my_int;
my_struct_t() : my_int(0) {
}
};
class my_iterator_t : public boost::iterator_facade<
my_iterator_t,
my_struct_t const,
boost::forward_traversal_tag
> {
private:
friend class boost::iterator_core_access;
my_struct_t my_struct;
public:
my_iterator_t() : my_struct() {
}
void increment() {
++ my_struct.my_int;
}
bool equal(my_iterator_t const& other) const {
return this->my_struct.my_int == other.my_struct.my_int;
}
my_struct_t const& dereference() const {
return my_struct;
}
};
int main() {
my_iterator_t my_iterator;
std::cout << my_iterator->my_int << "\n";
++my_iterator;
std::cout << my_iterator->my_int << "\n";
return 0;
}
I compile on Fedora 19 like this:
$ g++ test.cpp -std=gnu++0x -Weffc++ -o test
Here is the actual warning:
g++ test.cpp -std=gnu++0x -Weffc++ -o test
test.cpp:10:7: warning: base class ‘class boost::iterator_facade<my_iterator_t, const my_struct_t, boost::forward_traversal_tag>’ has a non-virtual destructor [-Weffc++]
class my_iterator_t : public boost::iterator_facade<
^
Thanks.
-Weffc++ option enables warnings about violations of the some style guidelines from Scott Meyers’ Effective C++ book. Your code violates the Item 7: Make destructors virtual in polymorphic base classes. So the compiler isn't complaining about your iterator, it's about the base class: boost::iterator_facade. I don't think you can eliminate the warning by modify your own code. As to why virtual destructor in polymorphic base classes are so important, a good answer is here.

Resources