I was following the official documentation for libsigc++-2.0 and I found this example:
class AlienDetector
{
public:
AlienDetector();
void run();
sigc::signal<void> signal_detected;
};
void warn_people()
{
cout << "There are aliens in the carpark!" << endl;
}
int main()
{
AlienDetector mydetector;
mydetector.signal_detected.connect( sigc::ptr_fun(warn_people) );
mydetector.run();
return 0;
}
As you can see both the run() function and the constructor for the AlienDetector class are not defined and therefore this code shouldn't compile ( but the doc takes for granted the fact that this code will work ).
Even more strange is the fact that if I define both run() and the constructor for the class, I can't see the effect of the library anyway, apparently the signal doesn't work and when run is called in the main no slot is activated.
I am forgetting about something here ? How this thing should be re-written ?
The documentation seems to be incomplete.
The most basic version of the code should look like:
AlienDetector::AlienDetector() {}
void AlienDetector::run() {
sleep(3); // wait for aliens
signal_detected.emit(); // panic
}
I've posted a fully functional make-based example on github, example1.cpp is the first example, example2.cpp is one using a member function.
To be more precise, that particular page of documentation is correct and presented as intended, but with a key link missing. I'll get to what is missing after reviewing what is there. The code that is listed as one block in the question is presented as two blocks in the documentation:
Here's my class:
<first code block, which
declares AlienDetector>
Here's your code that uses it:
<second code block, which
defines warn_people() and
main()>
This split is an important detail. The learning scenario being presented is one where you have to write code that interfaces with a certain class. In this sort of scenario, the information you have to work with is the declaration of that class, not the implementation of it (the header file, not the source). Hence, the first code block provides the declaration without code for the functions. The presentation appropriately leaves out the details that you should ignore at the moment.
The omission comes a bit further down the page:
To compile this example, use:
g++ example1.cc -o example1 `pkg-config --cflags --libs sigc++-2.0`
Hold on—"example1.cc"? What is that? You might notice that the page did not say how to create example1.cc. While it is somewhat natural to assume that one should copy the code from the page into this file, that is not what was intended. The author had intended that example1.cc be a pre-made file (with the missing function implementations) that would accompany the text. Somehow this file, and the others referenced later in the tutorial, never made it into the published product.
This omission has been known for a while (see some mail archives), but has not attracted the right sort of attention to fix it. (The tutorial was updated a few months after the emails I linked to, but apparently not to add the missing example files.) In the linked emails, the author provided a link to get the missing files, but in the decade+ since then, the link has expired.
Fortunately, Petesh has provided a longer-lived source for some example files in the older answer here. (As for me, I'm just being overly detailed and precise. Too bad I got lost when trying to figure out where this issue could be logged so that it could be addressed, or at least tracked.)
Related
I'm currently working on a C++ class for an ESP32. I want to implement resource allocation of the resources like: IO-Pins, available RMT channels and so on.
My idea is to do this with some kind of resource handler which checks this at compile time, but I have no good idea nor did I find anything about something like this yet.
To clarify my problem lets have an example of what I mean.
Microcontroller X has IO pins 1-5, each of these can be used by exactly one component.
Components don't know anything from each other an take the pin they should use as a ctor argument.
Now I want to have a class/method/... that checks if the pin, a component needs, is already allocated at compile time.
CompA a(5); //works well: 5 is not in use
CompB b(3); //same as before, without the next line it should compile
CompC c(5); //Pin 5 is already in use: does not compile!
Im not sure yet how to do so. My best guess (as I can't use defines here: users should be able to use it only by giving a parameter or template argument) is, that it might work with a template function, but I did not find any way of checking which other parameters have been passed to a template method/class yet.
Edit1: Parts of the program may be either autogenerated or user defined in a manner, they do not know about other pin usages. The allocation thus is a "security" feature which should disallow erroneous code. This should also forbid it, if the register functions are in different code pathes (even if they might exclude each other)
Edit2: I got a response, that compile time is wrong here as components might be compiled separated from another. So the only way to do so seems like a linker error.
A silly C-style method: you could desperately use __COUNTER__ as the constructor's argument. This dynamic macro increases itself after each appearance, starting with 0.
I hope there's a better solution.
Consider this mock-up of my situation.
in an external header:
class ThirdPartyObject
{
...
}
my code: (spread among a few headers and source files)
class ThirdPartyObjectWrapper
{
private:
ThirdPartyObject myObject;
}
class Owner
{
public:
Owner() {}
void initialize();
private:
ThirdPartyObjectWrapper myWrappedObject;
};
void Owner::initialize()
{
//not weird:
//ThirdPartyObjectWrapper testWrappedObject;
//weird:
//ThirdPartyObject testObject;
}
ThirdPartyObject is, naturally, an object defined by a third party (static precompiled) library I'm using. ThirdPartyObjectWrapper is a convenience class that eliminates a lot of boiler-plating for working with ThirdPartyObject. Owner::initialize() is called shortly after an instance of Owner is created.
Notice the two lines I have labeled as "weird" and "not weird" in Owner::initialize(). All I'm doing here is creating a couple of objects on the stack with their default constructors. I don't do anything with those objects and they get destroyed when they leave scope. There are no build or linker errors involved, I can uncomment either or both lines and the code will build.
However, if I uncomment "weird" then I get a segmentation fault, and (here's why I say it's weird) it's in a completely unrelated location. Not in the constructor of testObject, like you might expect, but in the constructor of Owner::myObjectWrapper::myObject. The weird line never even gets called, but somehow its presence or absence consistently changes the behavior of an unrelated function in a static library.
And consider that if I only uncomment "not weird" then it runs fine, executing the ThirdPartyObject constructor twice with no problems.
I've been working with C++ for a year so it's not really a surprise to me that something like this would be able happen, but I've about reached the limit of my ability to figure out how this gotcha is happening. I need the input of people with significantly more C++ experience than me.
What are some possibilities that could cause this to happen? What might be going on here?
Also, note, I'm not asking for advice on how to get rid of the segfault. Segfaults I understand, I suspect it's a simple race condition. What I don't understand is the behavior gotcha so that's the only thing I'm trying to get answers for.
My best lead is that it has to do with headers and macros. The third party library actually already has a couple of gotchas having to do with its headers and macros, for example the code won't build if you put your #include's in the wrong order. I'm not changing any #include's so strictly this still wouldn't make sense, but perhaps the compiler is optimizing includes based on the presence of a symbol here? (it would be the only mention of ThirdPartyObject in the file)
It also occurs to me that because I am using Qt, it could be that the Meta-Object Compiler (which generates supplementary code between compilations) might be involved in this. Very unlikely, as Qt has no knowledge of the third party library where the segfault is happening and this is not actually relevant to the functionality of the MOC (since at no point ThirdPartyObject is being passed as an argument), but it's worth investigating at least.
Related questions have suggested that it could be a relatively small buffer overflow or race condition that gets tripped up by compiler optimizations. Continuing to investigate but all leads are welcome.
Typical culprits:
Some build products are stale and not binary-compatible.
You have a memory bug that has corrupted the state of your process, and are seeing a manifestation of that in a completely unrelated location.
Fixing #1 is trivial: delete the build folder and build again. If you're not building in a shadow build folder, you've set yourself up for failure, hopefully you now know enough to stop :)
Fixing #2 is not trivial. View manual memory management and possible buffer overflows with suspicion. Use modern C++ programming techniques to leverage the compiler to help you out: store things by value, use containers, use smart pointers, and use iterators and range-for instead of pointers. Don't use C-style arrays. Abhor C-style APIs of the (Type * array, int count) kind - they don't belong in C++.
What fun. I've boiled this down to the bottom.
//#include <otherthirdpartyheader.h>
#include <thirdpartyobject.h>
int main(...)
{
ThirdPartyObject test;
return 0;
}
This code runs. If I uncomment the first include, delete all build artifacts, and build again, then it breaks. There's obviously a header/macro component, and probably some kind of compiler-optimization component. But, get this, according to the library documentation it should give me a segfault every time because I haven't been doing a required initialization step. So the fact that it runs at all indicates unexpected behavior.
I'm chalking this up to library-specific issues rather than broad spectrum C++ issues. I'll be contacting the vendor going forward from here, but thanks everyone for the help.
the project I'm working on currently consists of three basic build targets:
The core, containing almost all of the classes
The tests, containing only a few test classes and a main function. They touch (hopefully) every piece of code in the core.
The client, which only consists of a main function that used to create one object from the core and call what currently is a Hello World function. Now the main is completely empty and it didn't do anything to kill the error.
The linking error appears only if I build the client. It's about a static const in the core, looking like this:
class Transition
{
private:
Transition();
...more declarations...
public:
static const Transition NO_TRANSITION
...more declarations...
}
Usage in Map.cpp:
Transition Map::searchTransition(Coordinate p, Direction d)
{
...code...
return Transition::NO_TRANSITION;
}
This is what I'm told by by g++:
obj/gpp/Debug/Game/Map/Map.o:Map.cpp: (.rdata$.refptr._ZN10Transition13NO_TRANSIT
IONE[.refptr._ZN10Transition13NO_TRANSITIONE]+0x0): undefined reference to `Transition::NO_TRANSITION'
Map.cpp is also part of the core, it includes Transition.h, and the .o files are right where they are expected to be. There are no forward declarations between the two involved files.
What bothers me most: This only happens if I build the client. It works perfectly fine if I link the core with the test classes and their main instead, which means only more code to be linked. The only thing removed is a tiny or even empty main function that got replaced with a much bigger one that actually uses Map and Transition.
Also, that static const is not new and has never caused problems in the past. Since the tests accept it, I would think everything is perfectly fine, but apparently only as long as the tests are linked to it.
I've tried recreating the error in a smaller project, with the makefile being (mostly) the same, but the error won't show up. I have absolutely no idea what the important difference might be.
I'm using g++ 4.8 with -std=c++11 under cygwin. Visual Studio accepts the same code without trouble, and under true linux I couldn't test yet, though I expect it to be the same as with cygwin.
Does anybody have an idea what might be going wrong here?
EDIT: The "strange" behavior happened because there actually was a definition of Transition::NO_TRANSITION in the tests.
You only declared it and thus there's no physical location where its data are stored. You should add definition to your Transition source and link the created object file with your tests.
// Transition.cpp
#include "transition.h"
const Transition Transition::NO_TRANSITION;
Note that the linker works somehow lazily, i.e. the symbols you don't reference are not searched for, thus your older code that didn't use actual NO_TRANSITION physical location compiled and linked fine.
You have to define the static variable. In your CPP, add this line.
static const Transition::Transition NO_TRANSITION
That will do.
I would like to write a small tool that takes a C++ program (a single .cpp file), finds the "main" function and adds 2 function calls to it, one in the beginning and one in the end.
How can this be done? Can I use g++'s parsing mechanism (or any other parser)?
If you want to make it solid, use clang's libraries.
As suggested by some commenters, let me put forward my idea as an answer:
So basically, the idea is:
... original .cpp file ...
#include <yourHeader>
namespace {
SpecialClass specialClassInstance;
}
Where SpecialClass is something like:
class SpecialClass {
public:
SpecialClass() {
firstFunction();
}
~SpecialClass() {
secondFunction();
}
}
This way, you don't need to parse the C++ file. Since you are declaring a global, its constructor will run before main starts and its destructor will run after main returns.
The downside is that you don't get to know the relative order of when your global is constructed compared to others. So if you need to guarantee that firstFunction is called
before any other constructor elsewhere in the entire program, you're out of luck.
I've heard the GCC parser is both hard to use and even harder to get at without invoking the whole toolchain. I would try the clang C/C++ parser (libparse), and the tutorials linked in this question.
Adding a function at the beginning of main() and at the end of main() is a bad idea. What if someone calls return in the middle?.
A better idea is to instantiate a class at the beginning of main() and let that class destructor do the call function you want called at the end. This would ensure that that function always get called.
If you have control of your main program, you can hack a script to do this, and that's by far the easiet way. Simply make sure the insertion points are obvious (odd comments, required placement of tokens, you choose) and unique (including outlawing general coding practices if you have to, to ensure the uniqueness you need is real). Then a dumb string hacking tool to read the source, find the unique markers, and insert your desired calls will work fine.
If the souce of the main program comes from others sources, and you don't have control, then to do this well you need a full C++ program transformation engine. You don't want to build this yourself, as just the C++ parser is an enormous effort to get right. Others here have mentioned Clang and GCC as answers.
An alternative is our DMS Software Reengineering Toolkit with its C++ front end. DMS, using its C++ front end, can parse code (for a variety of C++ dialects), builds ASTs, carry out full name/type resolution to determine the meaning/definition/use of all symbols. It provides procedural and source-to-source transformations to enable changes to the AST, and can regenerate compilable source code complete with original comments.
Whilst refactoring some old code I realised that a particular header file was full of function declarations for functions long since removed from the .cpp file. Does anyone know of a tool that could find (and strip) these automatically?
You could if possible make a test.cpp file to call them all, the linker will flag the ones that have no code as unresolved, this way your test code only need compile and not worry about actually running.
PC-lint can be tunned for dedicated purpose:
I tested the following code against for your question:
void foo(int );
int main()
{
return 0;
}
lint.bat test_unused.cpp
and got the following result:
============================================================
--- Module: test_unused.cpp (C++)
--- Wrap-up for Module: test_unused.cpp
Info 752: local declarator 'foo(int)' (line 2, file test_unused.cpp) not referenced
test_unused.cpp(2) : Info 830: Location cited in prior message
============================================================
So you can pass the warning number 752 for your puropse:
lint.bat -"e*" +e752 test_unused.cpp
-e"*" will remove all the warnings and +e752 will turn on this specific one
If you index to code with Doxygen you can see from where is each function referenced. However, you would have to browse through each class (1 HTML page per class) and scan for those that don't have anything pointing to them.
Alternatively, you could use ctags to generate list of all functions in the code, and then use objdump or some similar tool to get list of all function in .o files - and then compare those lists. However, this can be problematic due to name mangling.
I don't think there is such thing because some functions not having a body in the actual source tree might be defined in some external library. This can only be done by creating a script which makes a list of declared functions in a header and verifies if they are sometimes called.
I have a C++ ftplugin for vim that is able is check and report unmatched functions -- vimmers, the ftplugin suite is not yet straightforward to install. The ftplugin is based on ctags results (hence its heuristic could be easily adapted to other environments), sometimes there are false positives in the case of inline functions.
HTH,
In addition Doxygen (#Milan Babuskov), you can see if there are warnings for this in your compiler. E.g. gcc has -Wunused-function for static functions; -fdump-ipa-cgraph.
I've heard good things about PC-Lint, but I imagine it's probably overkill for your needs.