I am writing a simple test program on Linux system by using g++ 4.3 and Rogue Wave library. The problem that I am facing here is that the following codes can be compiled but it would pop up a segmentation fault on this line when I run it:
_aClasses.insertKeyAndValue(100,1000);
When I run the same piece code on a HPUX machine by using aCC compiler. It runs smoothly which makes me confused. Is that because the way that g++ initialize the static variable is different from aCC does? Anyone knows what's going on here? Thanks in advance.
A.hxx
#include <rw/tvhdict.h>
#include <rw/cstring.h>
#include <rw/rwdate.h>
#include <rw/rstream.h>
using namespace std;
class A
{
public :
A();
static void add();
struct long_hash {
unsigned long operator() (const long& x) const { return x;};
};
struct long_equal {
RWBoolean operator() (const long& x, const long& y) const { return x==y;};
};
private:
static RWTValHashMap<long, long, long_hash, long_equal> _aClasses;
};
A.cxx
#include "A.hxx"
RWTValHashMap<long, long, A::long_hash, A::long_equal> A::_aClasses;
A::A()
{
cout<<"init A"<<endl;
}
void A::add()
{
_aClasses.insertKeyAndValue(100,1000);
}
B.hxx
class B
{
public:
B();
};
B.cxx
#include "B.hxx"
#include "A.hxx"
B::B()
{
A::add();
}
Main.cxx
#include "A.hxx"
#include "B.hxx"
static B c;
int main() {
cout<<"main"<<endl;
return 0;
}
The order of initialization of static members from different translation units (essentially different cpp/cxx files) is not specified. So whether static B c or RWTValHashMap<long, long, A::long_hash, A::long_equal> A::_aClasses will be initialized first can be different for different compilers and may even change when using the same compiler. It was simply luck that your previous compiler always initialized them in the desired order.
A way to avoid this is to use the 'construct on first use idiom'
Related
This question already has answers here:
C++ Multiple classes with same name
(5 answers)
Closed 6 years ago.
I have three files, main.cpp, a.cpp and b.cpp. The main() function just calls a function in a.cpp, and then in b.cpp -- and I get a SIGSEGV. As far as I can tell, it looks like the lambda functions used with my sort() are conflicting with each other. Compile command line order is important; if I compile the files via:
g++ -std=c++11 main.cpp a.cpp b.cpp
The code crashes (I get "*** stack smashing detected ***: ./a.out terminated"), but if I switch "a.cpp" and "b.cpp":
g++ -std=c++11 main.cpp b.cpp a.cpp
it runs fine (I'm not saying anything about whether it "works" or not, just SIGSEGV vs no-SIGSEGV).
Here's the smallest code samples I could generate for the three files:
main.cpp:
extern void spud1 (void);
extern void spud2 (void);
int
main (int argc, char **argv)
{
spud1 ();
spud2 ();
}
a.cpp:
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
struct Database
{
int pubdate;
string title;
string link;
};
static vector <Database> database;
void
spud1 (void)
{
int i;
for (i = 0; i < 20; i++) {
database.push_back ({});
}
sort(database.begin(), database.end(),
[] (const Database& a, const Database& b)
{
return (a.pubdate > b.pubdate);
});
}
b.cpp:
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
struct Database
{
unsigned serial;
double calories;
double carbs;
double sodium;
double sugar;
};
static vector <Database> database;
void
spud2 (void)
{
int i;
for (i = 0; i < 20; i++) {
database.push_back ({});
}
sort(database.begin(), database.end(),
[] (const Database& a, const Database& b)
{
return (a.serial > b.serial);
});
}
There are two things that bother me about this:
there's no indication from the toolchain that "something bad" is happening; there are no compiler or linker warnings, and
I have no way to make "struct Database" local to the module -- if I stick "static" in front of it I get an error: "a.cpp:13:1: error: a storage class can only be specified for objects and functions**`"
So, my question is, what am I doing wrong, and how can I get around it? (i.e., why is there no warning, is this "supposed" to happen? and how do I make my "Database" struct actually be local to the module? -- my workaround is to use different names, but I'm not happy with that.)
You can make the struct declarations/definitions private for the translation unit by putting them into an unnamed namespace:
namespace { // <<<<<<<<<<<<<<<<
struct Database
{
unsigned serial;
double calories;
double carbs;
double sodium;
double sugar;
};
}
Otherwise the linker will use what's found first, no matter if your lambda functions are module local as well.
That was learned from that same subtle bug, we spent on debugging 3 or 4 days in our production code. Not funny, no.
So I'm attempting to program chess in C++ and I decided to make my move handler its own class (it was a main function before) so I could use it in some of my other classes without having to copy it everywhere.
However, when I finished setting everything up I got this error: 'parseMove' : is not a member of '`global namespace''
I'm using the standard namespace and all public functions and variables, and I know that so please don't bring it up unless it's relevant. My IDE is MS Visual C++ 2012.
Here is the code:
In the main:
void playGame(){
...
MoveParser parser; //declare move handler
...
//example of use
parser.parseMove(current, currentX, currentY);
...
}
MoveParser.h:
#pragma once
#include <sstream>
#include <iostream>
#include <string>
using namespace std;
class MoveParser
{
public:
MoveParser(void);
~MoveParser(void);
void parseMove(string, int &, int &);
};
MoveParser.cpp:
#include "MoveParser.h"
MoveParser::MoveParser(void)
{
}
MoveParser::~MoveParser(void)
{
}
void::parseMove(string str, int &x, int &y){
//random junk
}
And also Visual C++ is giving me some new errors that aren't real...and I know they're not real because the code that it's giving me errors on ran fine before I added the new class and I haven't changed it.
Anyways, very frustrating, hopefully someone can point me in the right direction.
You forgot to specify the class name before the function name in its definition. Change this code
void::parseMove(string str, int &x, int &y){
//random junk
}
to
void MoveParser::parseMove(string str, int &x, int &y){
//random junk
}
I have these two files table.cpp and table.h in my program code apart from the main.cpp. The files are described as below
table.cpp
#include <iostream>
#include "table.h"
using namespace std;
// accessor function for Name
char* PeriodicTable::Name()
{
return Name;
}
// accessor function for Symbol
char* PeriodicTable::Symbol()
{
return Symbol;
}
table.h
#ifndef TABLE_H
#define TABLE_H
class PeriodicTable
{
char Name[15], Symbol[3], GroupName[20], Block, State[25], Colour[15], Classification[20];
int GroupNo, AtomicNo, PeriodNo;
float Weight;
public:
char* Name();
char* Symbol();
};
#endif
but the problem is that the IntelliSense(since I am using Visual C++ Express 2010) shows a red curved underline below the name and symbol in the accessor function in table.cpp. I can't understand why???
Your member functions and member variables have the same name. This is not possible in C++. That's why various conventions exist for naming member variables, e.g. m_name, name_ etc. (NB: When dealing with underscores in identifiers make sure you don't use a reserved name by accident.)
You might wonder why and how that could possibly go wrong. In your example there clearly is no way to invoke operator() on char[15], but the problem is that the compiler only knows that after performing semantic analysis. There could also be cases where it is impossible to disambiguate. For example:
struct Func {
void operator()() { };
};
struct C {
Func f;
void f() {}
};
int main() {
C c;
c.f(); // which one?
}
I want to bind a member to store a function object outside of the class instance. Howeber, in VS2012 this only works up to placeholders::_4, then it starts popping up with errors. Take this for example:
#include <iostream>
#include <functional>
using namespace std;
using namespace std::placeholders;
class A
{
public:
int method(int a,int b,int c,int d,int e)
{
return a;
}
};
int main()
{
std::function<int (int,int,int,int,int)> obj;
A a;
// error: no instance of overloaded function "std::bind" matches the argument list
obj = std::bind(&A::method,&a,_1,_2,_3,_4,_5);
std::cout << obj(1,2,3,4,5);
return 0;
}
The above code compiles fine on GCC 4.7.2 but causes the above-mentioned error in Visual Studio 2012. Are there any workarounds, is this a bug in VC++ or am I doing something dodgy here?
Since Visual Studiio does not support variadic templates this is solved by a define.
You can set a define _VARIADIC_MAX to the amount of params you need. Do this in your projects settings to that it is set before any system headers are included.
But keep in mind that setting this value to a large number will increase compile times.
One alternative would be to use a lambda instead like this:
#include <iostream>
#include <functional>
using namespace std;
using namespace std::placeholders;
class A
{
public:
int method(int a, int b, int c, int d, int e)
{
return a;
}
};
int main()
{
std::function<int(int, int, int, int, int)> obj;
A a;
obj = [&a](int b, int c, int d, int e, int f){return a.method(b,c,d,e,f); };
std::cout << obj(1, 2, 3, 4, 5);
return 0;
}
edit: it seems like this won't work either without following #mkaes answer, since apparently the definition of the std::function depends on it.
After I read the reference link: Must provide destructor in the PIMPL, I do the follow the example, but the g++(4.6.1) doesn't generate compile error as I expected
The source code is:
// Predeclare.h
#include <vector>
#include <boost/scoped_ptr.hpp>
#include <iostream>
struct A;
class Predeclare
{
std::vector<A> alist_;
boost::scoped_ptr<A> pa_;
//A a;
public:
Predeclare();
//~Predeclare();
void print();
void set(int i);
};
// Predeclare.cpp
#include "Predeclare.h"
struct A
{
int a;
};
Predeclare::Predeclare(): pa_(new A)
{}
/*
Predeclare::~Predeclare()
{}
*/
void Predeclare::print()
{
std::cout << pa_->a << '\n';
}
void Predeclare::set(int i)
{
pa_->a = i;
}
int main()
{
Predeclare c1;
c1.set(10);
c1.print();
return 0;
}
Then, compile the program
g++ Predeclare.cpp
Everything is ok, Why the g++(4.6.1) doesn't generate compile error?
In your example, the compiler only needs a destructor for Predeclare when it reaches the declaration of c1 in main(). By that point, A has already been defined, earlier in Predeclare.cpp.
If you were to try to instantiate Predeclare in a different source file, you would likely run into problems.
Note that instantiating std::vector<A> where A is incomplete yields undefined behavior. When you instantiate a container, the value type must be Destructible, and only complete types are Destructible.