I have a class for which I have overloaded the operator bool explicitly like this :-
class Foo {
explicit operator bool() {
// return_something_here
}
};
However, when I run the following two in gdb I get :-
gdb) p fooobj.operator bool()
$7 = true
gdb) p (bool)(fooobj)
$8 = false
What's the difference between the two invocations and why do they return different things?
Edit :- I'm using the clang compiler.
Note :- The second value (false) is the correct value that I want to be returned using the first syntax. I'm using a codegen so I don't have complete control over what c++ gets generated in case anyone is curious why I don't just use the second syntax.
Even in that case, the difference between the two would still be an unanswered question.
I just ran a few quick tests, and it appears to be that gdb doesn't handle code compiled with clang well. Here is a test program:
#include <iostream>
using namespace std;
class Foo {
public:
Foo() : m_Int(0) {}
operator bool() {
return true; // also tried false here
}
private:
int m_Int;
};
int main()
{
Foo f;
if (f.operator bool()) cout << "operator bool is true.\n";
if ((bool)f) cout << "(bool)f is true.\n";
return 0;
}
When the binary is run, the output is as expected, i.e. (bool)f is the same as f.operator bool(), regardless of the compiler. However, if gdb is used with code build using g++, then the p command behaves correctly. Yet when gdb is run on code built using clang++, I get:
(gdb) print f.operator bool()
Couldn't find method Foo::operatorbool
(gdb)
I'm running clang v. 3.4, gcc v. 4.8.4 on Ubuntu 14.04.
In fact, a quick search revealed this: Is it possible to debug a gcc-compiled program using lldb, or debug a clang-compiled program using gdb?. So, I tried lldb, and it worked as expected. This is consistent with the comment that was added as I was investigating.
Related
I have this piece of c++ code for sorting a struct,
const bool operator<(P& p) const {
//...
}
It compiles without any problem on a linux device with "gcc 4.9.2".
But if try it on a windows machine with "gcc 4.7.1" (the one that comes with Code::Blocks 13.12), it gives nasty errors that you can see here http://pastebin.com/S28tD9kc
For compiling in both cases I've used: "g++ -std=c++11"
If I change "operator<(P& p)" to "operator<(const P& p)" it magically works. OK no problem I've made some mistake, but why does the first one not work on a windows machine if it works on a linux machine without any sign of problem?
An example.
This is probably because in those gcc versions sort is implemented differently. I have checked under VS2005 and it also produces such errors, but from looking into my stl implementation - I see lots of const T& parameters used when sorting. This will cause the same error you see if operator< is used with no const& parameter. I was able to compile such code using custom comparator and const_cast:
struct my_comp {
bool operator() (const P& a, const P& b) const {
return const_cast<P&>(a).operator<(const_cast<P&>(b));
}
};
std::vector<P> pp(10);
std::sort(pp.begin(), pp.end(), my_comp());
I am not sure if this is correct code,just wrote it for compile experiment.
On the other hand, under Visual Studio 2015 it all compiles fine with non const parameter in operator<. In VS2015 sort uses move semantics, and this is what I suppose makes it compile.
Let's consider the following three files.
tclass.h:
#include <iostream>
#include <vector>
template<typename rt>
class tclass
{
public:
void wrapper()
{
//Storage is empty
for(auto it:storage)
{
}
try
{
thrower();
}
catch(...)
{
std::cout << "Catch in wrapper\n";
}
}
private:
void thrower(){}
std::vector<int> storage;
};
spec.cpp:
#include "tclass.h"
//The exact type does not matter here, we just need to call the specialized method.
template<>
void tclass<long double>::thrower()
{
//Again, the exception may have any type.
throw (double)2;
}
main.cpp:
#include "tclass.h"
#include <iostream>
int main()
{
tclass<long double> foo;
try
{
foo.wrapper();
}
catch(...)
{
std::cerr << "Catch in main\n";
return 4;
}
return 0;
}
I use Linux x64, gcc 4.7.2, the files are compiled with this command:
g++ --std=c++11 *.cpp
First test: if we run the program above, it says:
terminate called after throwing an instance of 'double'
Aborted
Second test: if we comment for(auto it:storage) in the tclass.h file, the program will catch the exception in main function. WATWhy? Is it a stack corruption caused by an attempt to iterate over the empty vector?
Third test: lets uncomment back the for(auto it:storage) line and move the method specialization from spec.cpp to main.cpp. Then the exception is caught in wrapper. How is it possible and why does possible memory corruption not affect this case?
I also tried to compile it with different optimization levels and with -g, but results were the same.
Then I tried it on Windows 7 x64, VS2012 express, compiling with x64 version of cl.exe with no extra command line arguments. At the first test this program produced no output, so I think it just crashed silently, so the result is similar with Linux version. For the second test it produced no output again, so result is different from Linux. For the third test the result was similar with Linux result.
Are there any errors in this code so they can lead to such behavior? May the results of the first test be caused by possible bug in compilers?
With your code, I have with gcc 4.7.1:
spec.cpp:6: multiple definition of 'tclass<long double>::thrower()'
You may correct your code by declaring the specialization in your .h as:
template<> void tclass<long double>::thrower();
I have a program that I'd like to debug by setting a breakpoint in a non-default constructor, but the breakpoint I set is never hit. Below is an example program where this problem comes up. There is no problem hitting breakpoints set in the main function, but any breakpoints set in the Domain.cpp file are ignored:
Main.cpp:
#include <iostream>
#include "Domain.h"
int main()
{
Domain y;
std::cout << y.x << std::endl; // <- No problem setting breakpoint here
return 0;
}
Domain.cpp:
#include "Domain.h"
Domain::Domain()
{
x = 4; // <- A breakpoint here is skipped
}
Domain.h:
#ifndef DOMAIN_H_
#define DOMAIN_H_
class Domain
{
public:
int x;
public:
Domain();
};
#endif /* DOMAIN_H_ */
However, the problem does not exist if I put everything into a single file:
Main2.cpp:
#include <iostream>
int main()
{
class Domain
{
public:
int x;
Domain()
{
x = 4; // <- No problem setting breakpoint here now!
};
};
Domain y;
std::cout << y.x << std::endl;
return 0;
}
Why is this the case? How can I change this so that I'm able to set breakpoints when I use multiple files?
I can confirm that the breakpoints aren't working both when I run the debugger manually in a terminal and when I run it through Eclipse CDT, where I get the same error discussed in this question which was apparently never answered:
Why does Eclipse CDT ignore breakpoints?
I am using:
Eclipse Kepler
Mac OSX 10.8.4
gdb 6.3.5 (Apple version)
gcc 4.2.1 with -O0 and -g3 flags
Please be patient with me. I'm still learning the ropes.
You are likely hitting this GDB bug.
This bug has long been fixed, but your version of GDB is very old (and Apple is unlikely to update it).
This is a very interesting anomaly that I would like to explore further, but I suspect it's related to Eclipse's default GCC settings. Many super basic functions like these get optimized out when they hit the compiler. (one time I tried to track a simple for loop, but the viable was removed entirely on GCC's highest optimization settings)
Below are two simplified code examples: the first one compiles just fine, the second one emits a compile error (no operator << found which takes a left hand operator ByteVector...).
The only difference in between the two examples is the placement of the using directive.
I don't want to know why it fails (you got not enough information to answer this), I am only interested in why it does make any difference where I place the using.
I would have expected the exact same behaviour in both examples.
Compiles without error
ByteVector Test()
{
using Base::operator <<;
ByteVector foo;
int bar = 1;
foo << bar;
return foo;
}
Compiles with error
using Base::operator <<;
ByteVector Test()
{
...same as above, without using
}
Extra information:
The operator<< used is defined as follows
template<typename T>
ByteVector& operator<<(ByteVector &, const T&){...};
The only thing that comes to my mind is Visual Studio. If that was the case, you may want to put the using directive right after the corresponding #include. As the remark on the page says:
Putt your using directive at the beginning of the source code file to
reduce the potential for unexpected behavior with IntelliSense.
Otherwise, it shouldn't make any difference.
I have 2 methods in C++ class as follows:
class myClass {
public:
void operator()( string myString ) {
// Some code
}
void myMethod() { ... }
}
For a regular method, I can simply set the breakpoint in GDB as:
b myClass::myMethod
But how do I set the breakpoint for the first method?
UPDATE:
The suggestions from initial answers (b myClass ::operator()) does not work :(
b myClass::operator()
Function "myClass::operator()" not defined.
Thanks!
gdb will also take breakpoints at specific line numbers. For example
b file.cc:45
Just the same. myClass::operator()(string) is a regular method.
If you have several overloaded operator() methods (e.g. a const and a non-const version) gdb should offer the choice where to set the breakpoint:
http://sunsite.ualberta.ca/Documentation/Gnu/gdb-5.0/html_node/gdb_35.html#SEC35
You may have to make sure that method operator()(string) is actually compiled.
Edit:
I've tested the following file test.cpp:
#include <string>
#include <iostream>
class myClass {
public:
void operator()( int i ) {
std::cout << "operator()";
}
void myMethod() {
std::cout << "myMethod";
}
};
int main() {
myClass c;
c(1);
c.myMethod();
return 0;
}
Compiled with g++ test.cpp -o test, ran gdb test (version GNU gdb 6.3.50-20050815 (Apple version gdb-1344)), typed start and only then could I set breakpoints.
b 'myClass::operator()(string)' and
b myClass::operator()
both worked.
Some C++ functions names can be really hard to type out correctly. Worse yet, gdb's autocompletion often gets confused with c++ names. I use this trick
gdb> break 'myClass::operator()<TAB>
Note the single quote at the beginning of the function. That helps gdb's autocompleter.
b myClass::operator()