Error when compiling ncurses - embedded-linux

I'm trying to compile ncurses 5.9 for an embedded system (using buildroot) and I get this error message:
In file included from ../c++/cursesm.h:39:0,
from ../c++/cursesm.cc:35:
../c++/cursesp.h: In member function ‘T* NCursesUserPanel<T>::UserData() const’:
../c++/cursesp.h:256:43: error: no matching function for call to
‘NCursesUserPanel<T>::get_user() const’
return reinterpret_cast<T*>(get_user ());
Here's the code in question:
/* We use templates to provide a typesafe mechanism to associate
* user data with a panel. A NCursesUserPanel<T> is a panel
* associated with some user data of type T.
*/
template<class T> class NCursesUserPanel : public NCursesPanel
{
public:
NCursesUserPanel (int nlines,
int ncols,
int begin_y = 0,
int begin_x = 0,
const T* p_UserData = STATIC_CAST(T*)(0))
: NCursesPanel (nlines, ncols, begin_y, begin_x)
{
if (p)
set_user (const_cast<void *>(p_UserData));
};
// This creates an user panel of the requested size with associated
// user data pointed to by p_UserData.
NCursesUserPanel(const T* p_UserData = STATIC_CAST(T*)(0)) : NCursesPanel()
{
if (p)
set_user(const_cast<void *>(p_UserData));
};
// This creates an user panel associated with the ::stdscr and user data
// pointed to by p_UserData.
virtual ~NCursesUserPanel() {};
T* UserData (void) const
{
return reinterpret_cast<T*>(get_user ());
};
// Retrieve the user data associated with the panel.
virtual void setUserData (const T* p_UserData)
{
if (p)
set_user (const_cast<void *>(p_UserData));
}
// Associate the user panel with the user data pointed to by p_UserData.
};
Line 256 is this one: return reinterpret_cast<T*>(get_user ());

The problem here was due to a compiler update to g++ (Debian 7.2.0-5). New compilers have better error handling, and this old code was written without its benefit. The solution here is to either use a more recent version of ncurses (no-go for my particular situation) or use an older compiler. Since my host system is Debian, I used update-alternatives to switch to g++ 6.4 and the problematic error message went away.
I'm leaving this here because Google gave me no good results for the error message.

Related

A crash on V8' Context::New

I implement a wrapper around the Google V8 engine. I wrote a class:
class Es
{
public:
Es();
~Es();
int Init(const char* exec_path);
int CreateContext(uint& id);
int RemoveContext(const uint id);
protected:
Global<Context> global_context;
std::map<uint, Persistent<Context>*> contexts;
Isolate* isolate = nullptr;
private:
uint next_id = 1;
};
I want to create Contexts, hold them in the contexts var, and remove them oneday. So, I init the V8 engine:
int Es::Init(const char* exec_path)
{
v8::V8::InitializeICUDefaultLocation(exec_path);
v8::V8::InitializeExternalStartupData(exec_path);
std::unique_ptr<Platform> platform = platform::NewDefaultPlatform();
V8::InitializePlatform(platform.get());
V8::Initialize();
Isolate::CreateParams create_params;
create_params.array_buffer_allocator = ArrayBuffer::Allocator::NewDefaultAllocator();
isolate = Isolate::New(create_params);
if (!isolate)
return InitError;
return Success;
}
And after that I want to create a context, using int Es::CreateContext(uint& id). Its called after Init.
int EasyProspect::CreateContext(uint& id)
{
if (!isolate)
return NotInitializedError;
Isolate::Scope isolate_scope(isolate);
HandleScope handle_scope(isolate);
Local<Context> local_context = Context::New(isolate);
Persistent<Context> context(isolate, local_context);
contexts.emplace(id, &context);
return Success;
}
But I can't do that, the code crashes on Context::New(isolate). Why? isolate is not null, I enter the local scope...
Your best bet is to compile in Debug mode and run in a debugger. Then it should be easy to tell what's causing the crash.
(At the very least, you should post a complete reproducible example, including specifying the V8 version you're working with, how that's built/configured, and how you're compiling your code.)
If I had to guess: the Platform and the ArrayBuffer::Allocator need to stay alive for as long as you want to use the V8 instance, but in your code they are both destroyed at the end of Es::Init. Since Es is a wrapper class, you can easily add fields there to keep them around.

Creating custom gcc attribute to instrument specific functions: whitelisting, not blacklisting

I'm using gcc's -finstrument-functions option. To minimize the overhead, I want to instrument only a few functions. However, gcc only lets you blacklist functions (with the no_instrument_function attribute, or by providing a list of paths). It doesn't let you whitelist functions.
So I wrote a small gcc plugin adding an instrument_function attribute. This lets me set the instrumentation "flag" for a specific function (or, rather, clear the no instrumentation flag):
tree handle_instrument_function_attribute(
tree * node,
tree name,
tree args,
int flags,
bool * no_add_attrs)
{
tree decl = *node;
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT(decl) = 0;
return NULL_TREE;
}
However, from my understanding, this does not work. Looking at the gcc source, for this flag to actually do anything, you need to also use -finstrument-functions. See gcc/gimplify.c:14436:
...
/* If we're instrumenting function entry/exit, then prepend the call to
the entry hook and wrap the whole function in a TRY_FINALLY_EXPR to
catch the exit hook. */
/* ??? Add some way to ignore exceptions for this TFE. */
if (flag_instrument_function_entry_exit
&& !DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (fndecl)
/* Do not instrument extern inline functions. */
&& !(DECL_DECLARED_INLINE_P (fndecl)
&& DECL_EXTERNAL (fndecl)
&& DECL_DISREGARD_INLINE_LIMITS (fndecl))
&& !flag_instrument_functions_exclude_p (fndecl))
...
It first checks that the global -finstrument-functions flag is enabled. Then it checks a specific function's flag, which, from what I understand, is enabled by default. So all other functions that don't have my instrument_function attribute would still be instrumented.
Is there a way to clear this flag for all functions first, then handle my instrument_function attribute to set the flag for those functions only?
The trick was only defining the attribute, but not actually using any handling function, and do the processing elsewhere.
We still use -finstrument-functions to enable instrumentation for all functions at first. We can register a callback for PLUGIN_FINISH_PARSE_FUNCTION, which checks everything. For every function declaration, it checks its attributes. If it has the instrument_function attribute, it sets the flag for the instrumentation to be added later as usual. If the function doesn't have the attribute, it clears the flag.
#include <stdio.h>
#include "gcc-plugin.h"
#include "plugin-version.h"
#include "tree.h"
int plugin_is_GPL_compatible;
static struct plugin_info info = {
"0.0.1",
"This plugin provides the instrument_function attribute.",
};
static struct attribute_spec instrument_function_attr =
{
"instrument_function",
0,
-1,
false,
false,
false,
NULL, // No need for a handling function
};
static void register_attributes(void * event_data, void * data)
{
register_attribute(&instrument_function_attr);
}
void handle(void * event_data, void * data)
{
tree fndecl = (tree) event_data;
// Make sure it's a function
if (TREE_CODE(fndecl) == FUNCTION_DECL)
{
// If the function has our attribute, enable instrumentation,
// otherwise explicitly disable it
if (lookup_attribute("instrument_function", DECL_ATTRIBUTES(fndecl)) != NULL_TREE)
{
printf("instrument_function: (%s:%d) %s\n",
DECL_SOURCE_FILE(fndecl),
DECL_SOURCE_LINE(fndecl),
get_name(fndecl));
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT(fndecl) = 0;
}
else
{
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT(fndecl) = 1;
}
}
}
int plugin_init(
struct plugin_name_args * plugin_info,
struct plugin_gcc_version * version)
{
register_callback(
plugin_info->base_name,
PLUGIN_INFO,
NULL,
&info);
register_callback(
plugin_info->base_name,
PLUGIN_FINISH_PARSE_FUNCTION,
handle,
NULL);
register_callback(
plugin_info->base_name,
PLUGIN_ATTRIBUTES,
register_attributes,
NULL);
return 0;
}

ABI-compatible shared_ptr implementation

I am working on a COM-style complier cross-compatible plugin framework relying on compatible virtual table implementations for ABI compatibility.
I define interfaces containing only pure virtual member functions and an overridden delete operator to channel destruction to the place of implementation.
This works well with extern "C" factory functions instantiating the plugin implementation of the interface and returning an interface-type pointer.
However, I was wondering if smart pointers wouldn't be a more modern way to manage the lifetime of the plugin object. I think I have actually managed to
create a standard-layout shared_ptr/weak_ptr that uses a reference count object defined and implemented the same way as the plugin interfaces.
It looks something like this:
class IRefCount
{
public:
virtual void incRef() = 0;
virtual void decRef() = 0;
virtual bool incRefIfNZ() = 0;
virtual void incWRef() = 0;
virtual void decWRef() = 0;
virtual long uses() const = 0;
protected:
~ref_count_base() = default; //prohibit automatic storage
}
template <typename Ty>
class shared_ptr
{
private:
Ty* ptr_;
IRefCount* ref_count_;
public:
//member functions as defined by C++11 spec
}
Three questions:
Before the smart pointer the factory function looked like this:
extern "C" IPlugin* factory() { try { return new Plugin(); } catch (...) { return nullptr; } }
Now, it looks like this:
extern "C" shared_ptr<IPlugin> factory() { try { return shared_ptr<IPlugin>(new Plugin()); } catch (...) { return nullptr; } }
VS2013 is giving me warning C4190: 'factory' has C-linkage specified, but returns UDT 'shared_ptr' which is incompatible with C. According to MSDN this is OK, provided that both caller and callee are C++.
Are there any other potential issues with returning standard-layout objects from "C" linkage functions?
Calling conventions. Should I be specifying __stdcall for all pure-virtual interface functions and factory functions?
I am using <atomic> for the reference count. I am writing platform-independent code and I have not yet tried compiling for ARM. According to http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dht0008a/ch01s02s01.html armcc does not implement std::atomic. Any better compilers/stl out there?

where should I put the specialized std::hash for user defined type

I searched many pages, and I think I have known how to write the std::hash. But I don't know where to put it.
An example is presented here http://en.cppreference.com/w/cpp/utility/hash .
However, I defined my type Instance in namespace ca in file instance_management.h. I want to use unordered_set<Instance> in the same file in another class InstanceManager. So I write the following code:
namespace std
{
template <> struct hash<ca::Instance>
{
size_t operator()(const ca::Instance & instance) const
{
std::size_t seed = 0;
// Some hash value calculation here.
return seed;
}
};
} // namespace std
But where should I put it? I tried many locations but all failed.
I am using visual studio 2013. I tried to put the previous code in some locations but all failed to compile it.
// location 1
namespace ca
{
class Instance {...}
class InstanceManager
{
// ... some other things.
private unordered_set<Instance>;
}
}
// location 2
There are several ways.
Specializing std::hash
In your code make sure that your std::hash<Instance> specialization is preceded immediately by the Instance class definition, and followed by the use of the unordered_set container that uses it.
namespace ca
{
class Instance {...};
}
namespaces std {
template<> hash<Instance> { ... };
}
namespace ca {
class InstanceManager
{
// ... some other things.
private unordered_set<Instance>;
}
}
One drawback is that you can have funny name lookup interference when passing a std::hash<ca::Instance> to other functions. The reason is that the associated namespace (ca) of all the template arguments of std::hash can be used during name lookup (ADL). Such errors are a bit rare, but if they occur they can be hard to debug.
See this Q&A for more details.
Passing your hash to unordered_set
struct MyInstanceHash { ... };
using MyUnorderedSet = std:unordered_set<Instance, MyInstanceHash>;
Here, you simply pass your own hash function to the container and be done with it. The drawback is that you have to explicitly type your own container.
Using hash_append
Note, however, there is the N3980 Standard proposal is currently pending for review. This proposal features a much superior design that uses a universal hash function that takes an arbitrary byte stream to be hashed by its template parameter (the actual hashing algorithm)
template <class HashAlgorithm>
struct uhash
{
using result_type = typename HashAlgorithm::result_type;
template <class T>
result_type
operator()(T const& t) const noexcept
{
HashAlgorithm h;
using std::hash_append;
hash_append(h, t);
return static_cast<result_type>(h);
}
};
A user-defined class X then has to provide the proper hash_append through which it presents itself as a byte stream, ready to be hashed by the univeral hasher.
class X
{
std::tuple<short, unsigned char, unsigned char> date_;
std::vector<std::pair<int, int>> data_;
public:
// ...
friend bool operator==(X const& x, X const& y)
{
return std::tie(x.date_, x.data_) == std::tie(y.date_, y.data_);
}
// Hook into the system like this
template <class HashAlgorithm>
friend void hash_append(HashAlgorithm& h, X const& x) noexcept
{
using std::hash_append;
hash_append(h, x.date_);
hash_append(h, x.data_);
}
}
For more details, see the presentation by the author #HowardHinnant at CppCon14 (slides, video). Full source code by both the author and Bloomberg is available.
Do not specialise std::hash, instead write your own hash function object (see Edge_Hash below) and declare your unordered_set with two template arguments.
#include <unordered_set>
#include <functional>
namespace foo
{
// an edge is a link between two nodes
struct Edge
{
size_t src, dst;
};
// this is an example of symmetric hash (suitable for undirected graphs)
struct Edge_Hash
{
inline size_t operator() ( const Edge& e ) const
{
static std::hash<size_t> H;
return H(e.src) ^ H(e.dst);
}
};
// this keeps all edges in a set based on their hash value
struct Edge_Set
{
// I think this is what you're trying to do?
std::unordered_set<Edge,Edge_Hash> edges;
};
}
int main()
{
foo::Edge_Set e;
}
Related posts are, eg:
Inserting in unordered_set using custom hash function
Trouble creating custom hash function unordered_map
Thanks to everyone.
I have found the reason and solved the problem somehow: visual studio accepted the InstanceHash when I was defining instances_. Since I was changing the use of set to unordered_set, I forgot to specify InstanceHash when I tried to get the const_iterator, so this time the compiler tried to use the std::hash<> things and failed. But the compiler didn't locate the line using const_iterator, so I mistakenly thought it didn't accept InstanceHash when I was defining instances_.
I also tried to specialize the std::hash<> for class Instance. However, this specialization requires at least the declaration of class ca::Instance and some of its member functions to calculate the hash value. After this specialization, the definition of class ca::InstanceManage will use it.
I now generally put declarations and implementations of almost every classes and member functions together. So, the thing I need to do is probably to split the ca namespace scope to 2 parts and put the std{ template <> struct hash<ca::Instance>{...}} in the middle.

C++11 Lambda function compilation error

i am new using c++11 features and also tryng to use SDL_Widget-2 lib for build a simple Gui for my project. But i am getting stuck in the problem :
#include "sdl-widgets.h"
class Builder
{
public:
Builder():top_win(nullptr)
,but(nullptr)
{
top_win=new TopWin("Hello",Rect(100,100,120,100),0,0,false,
[]() {
top_win->clear();
draw_title_ttf->draw_string(top_win->render,"Hello world!",Point(20,40));
}
);
but=new Button(top_win,0,Rect(5,10,60,0),"catch me",
[](Button *b) {
static int dy=60;
b->hide();
b->move(0,dy);
b->hidden=false;
dy= dy==60 ? -60 : 60;
});
}
private:
TopWin * top_win;
Button *but;
};
int main(int,char**) {
Builder aViewBuilder;
get_events();
return 0;
}
with the error in the compilation stage:
In lambda function:
error: 'this' was not captured for this lambda function
error: 'this' was not captured for this lambda function
this error is printed out twice int the console.
I have try :
[this](){}
[=](){}
and
[&](){}
with different compile error but a cannot go more further.
Can any see a fix?
You do need to capture with [this] or [&]. I suspect that the TopWin and Button constructors take raw function pointers, and need to take std::functions instead.
A plain vanilla function pointer is not compatible with capturing lambdas. std::function is able to work like a function pointer that also allows safe storage of captured data. (i.e. the captured objects will need to be properly copied or destroyed when the function object is itself copied or destroyed)

Resources