Undefined refernce static member C++ [duplicate] - c++

This question already has answers here:
Can't set value of static object field (error LNK2001: unresolved external symbol)
(2 answers)
Closed 8 years ago.
I'm sick of this, I'm really exhausted. I am new in C++. But I have read a lot about that ,but still doesn't understand what is the correct to implement this.
I have just copied all code from this article Signal Handling in C++
BUT it still doesn't work !!!! I created new class Signal Handler.... Copy everything from this article BUT still this .... error message "Undefined reference .......". I am really confused about this. Please explain how to do this correctly and why I always get this message.
Here is just code copied from the article.
SignalHandler.h
#ifndef SIGNALHANDLER_H
#define SIGNALHANDLER_H
#include "eventhandler.h"
#include <signal.h>
class SignalHandler
{
public:
// Entry point.
static SignalHandler *getInstance (void);
// Register an event handler <eh> for <signum>
// and return a pointer to any existing <Event_Handler>
// that was previously registered to handle <signum>.
EventHandler* registerHandler (int signum,EventHandler *eh);
// Remove the <Event_Handler> for <signum>
// by setting the slot in the <signal_handlers_>
// table to NULL.
int removeHandler (int signum);
private:
// Ensure we're a Singleton.
SignalHandler (void);
// Singleton pointer.
static SignalHandler *instance;
// Entry point adapter installed into <sigaction>
// (must be a static method or a stand-alone
// extern "C" function).
static void dispatcher (int signum);
// Table of pointers to concrete <Event_Handler>s
// registered by applications. NSIG is the number of
// signals defined in </usr/include/sys/signal.h>.
static EventHandler *signalHandlers[NSIG];
};
#endif // SIGNALHANDLER_H
SignalHandler.cpp
#include "signalhandler.h"
EventHandler* SignalHandler::registerHandler (int signum,EventHandler *eh)
{
// Copy the <old_eh> from the <signum> slot in
// the <signal_handlers_> table.
EventHandler *oldEh = SignalHandler::signalHandlers[signum];
// Store <eh> into the <signum> slot in the
// <signal_handlers_> table.
SignalHandler::signalHandlers[signum] = eh;
// Register the <dispatcher> to handle this
// <signum>.
struct sigaction sa;
sa.sa_handler = SignalHandler::dispatcher;
sigemptyset (&sa.sa_mask);
sa.sa_flags = 0;
sigaction (signum, &sa, 0);
return oldEh;
}
void SignalHandler::dispatcher (int signum)
{
// Perform a sanity check...
if (SignalHandler::signalHandlers[signum] != 0) {
// Dispatch the handler's hook method.
SignalHandler::signalHandlers[signum]->handleSignal(signum);
}
}
WHY am I getting this messages ...............
error: undefined reference to `SignalHandler::signalHandlers'
error: undefined reference to `SignalHandler::signalHandlers'
Note that I have just copied this from the article.
I really hope for your help.Thanks.

You have to define the static array. Inside the class definition it is only declared. Write in the cpp module
EventHandler * SignalHandler::signalHandlers[NSIG];

Every function and object which is ODR-used must be defined.
And static SignalHandler *instance; in class-scope only declares that member, it does not define it.
Add the definition to exactly one translation-unit (.cpp-file).
SignalHandler* Signalhandler::instance;
Same for all the other static members.

Related

sa_handler function; can't access class member

I am trying to build a multi threaded program that will create four instances of a Child and "run" a set of "expensive" Jobs. The parent will send a signal indicating when they shall all start. Now, each child thread must then catch that signal. It has inside of it a sig_handler. It's a private class inside of Child.
So far I have it defined as:
private:
class sig_handler {
typedef struct sigaction sigAct;
Shared* sh;
//============
void whatSig();
public:
sig_handler( Shared* s );
sigAct action;
sigset_t signalset; // Just want siguser and sigquit
static void catchSig( int sig ); // interacts with the shared resource
// it starts up the threads
};
First off, is it even ok to have a class as a signal handler? If it is ok (which would certainly make the readibility better), how would we implement it?
I am trying to catch SIGUSR1 so that I can change a flag in Shared memory. Each thread has access to Shared memory through a pointer to this object, i.e. Shared* share. This is done using a class to act as a kind of shared base.
Now here is what I really need answered. I begin setting up my sigset_t signalSet:
Child::sig_handler::sig_handler( Shared* s ) {
sh = s;
sigemptyset(&signalset);
sigaddset(&signalset, SIGUSR1); // Add these to the now empty set
sigaddset(&signalset, SIGQUIT);
action.sa_handler = catchSig; // 1
action.sa_mask = signalset;
action.sa_flags = 0;
sigaction(SIGUSR1, &action, NULL); // attach the class member action
}
Really pay attention to line 1. This is a critical spot. This I think has to be a static or global function. This is where an error can be happening. When I make my class method catchSig(int sig) non static, line 1 complains Reference to a non-static function call must be called. I have it defined as such when this happens: void catchSig( int sig );
When I define it as static void catchSig( int sig );, the compiler complains on line 2.
void Child::sig_handler::catchSig(int sig) {
sh->startflag; // 2
}
It says, Invalid use of 'sh' in static member function. I need to be able to have access to this variable. How can I fix it so that I can have my sig_handler class, and share through catchSig()?
Update:
I implemented StoryTeller's suggestion of using a pointer to this. While it worked to stop the complaining of the compiler, I still have a buildtime error. I altered the definition of sig_handler to now be this:
private:
class sig_handler {
typedef struct sigaction sigAct;
Shared* sh;
static sig_handler* self;
//============
void whatSig();
public:
sig_handler( Shared* s );
sigAct action;
sigset_t signalset;
static void catchSig( int sig ); // interacts with the shared resource
// it starts up the threads
};
Take note of the new static pointer to itself. This was done so that I can have access to the variable sh, the shared resource that I need. Which I use as such:
void Child::sig_handler::catchSig(int sig) {
self->sh->setStartFlag(true); // this was were it used to complain
}
The sig_handler is created in the Child constructor (sigHand = new sig_handler(share)). I get a build time error stated below. What is happening? How can this be fixed?
"Child::sig_handler::self", referenced from:
Child::sig_handler::sig_handler(Shared*) in Child.o
Child::sig_handler::catchSig(int) in Child.o
ld: symbol(s) not found for architecture x86_64
Update 2:
Essentially, it's not possible to make a sig_handler class unfortunately.

Interruption handling with non-static member function

I am trying to do interruption handling with a member function from a class.
The code is
signal(SIGABRT, socketServer.signalHandler);
where the definition of signalHandler is
public:
void SocketServer::signalHandler(int sig)
{
logger.info("Receive SIG"+to_string(sig)+" Stopping server now...");
stop();
}
When I compile the code, I got an error says
main.cpp:32:32: error: reference to non-static member function must be called
signal(SIGABRT, socketServer.signalHandler);
I am trying to capture SIGABRT using this signalHandler function and to clean up and stop the socketServer instance. I guess I can use global variable and a global function to do the job, but any thoughts about doing this with a member function?
No, you can not do this.
The reason is that all member functions have an "implied/hidden" this pointer argument. If we "flattened" out your handler definition to produce the C equivalent, it would look like:
void SocketServer::signalHandler(SocketServer *this,int sig);
The signal function [in C] knows nothing of this [pun intended]. If it compiled, the handler would be called with sig going into the this argument and not the sig argument.
So, you really must do:
SocketServer my_global_server;
void
my_handler(int sig)
{
my_global_server.signalHandler(sig);
}
int
main(void)
{
signal(SIGABRT,my_handler);
return 0;
}
Actually, the above is quite dangerous because my_global_server may be in an indeterminate state when the signal handler is called, causing UB. Also, when in a signal handler, there are a limited number of things you are permitted to do. For example, no heap manipulations are permitted.
Here is a better way to implement this:
volatile int signal_flag;
SocketServer my_global_server;
void
my_handler(int sig)
{
signal_flag = sig;
}
int
main(void)
{
signal(SIGABRT,my_handler);
while (! signal_flag) {
...
}
my_global_server.signalHandler(signal_flag);
return 0;
}

Alternative to postThreadMessage/peekmessage?

There's a (static) thread in my C++ application, frequently doing something. To exchange information between the thread and my application I use methods PostThreadMessage and PeekMessage.
Due to some reason I can't use these methods anymore but don't know a good alternative. Does anybody have an advice? I just want to exchange simple parameters.
There's no reason why you can't "exchange simple object with the main thread" as you said in a comment. A common pattern for sharing an instance of a class between threads is to do something like this:-
Declare your class with a static function that can be targeted by _beginthread and an instance function that does the work:
class CMyClass
{
// ... other class declarations ...
private:
static void __cdecl _ThreadInit(void *pParam); // thread initial function
void ThreadFunction(); // thread instance function
void StartThread(); // function to spawn a thread
// ... other class declarations ...
};
Define the functions something like this:
void CMyClass::StartThread()
{
// function to spawn a thread (pass a pointer to this instance)
_beginthread(CMyClass::_ThreadInit, 0, this);
}
void __cdecl CMyClass:_ThreadInit(void *pParam)
{
// thread initial function - delegate to instance
CMyClass *pInstance = (CMyClass*)pParam;
pInstance->ThreadFunction();
}
void CMyClass:ThreadFunction()
{
// thread instance function is running on another
// thread but has (hopefully synchronised) access
// to all of the member variables of the CMyClass
// that spawned it ....
}
Makes sense? The general idea is just to use the static function with a passed this pointer to connect back to a specific instance of the class.

Error C2280: 'std::thread::thread(const std::thread &)' : attempting to reference a deleted function

I'm having a problem trying to create a VC++ Static Library that uses C++11 standard threads.
I currently have two classes, and I am able to declare and later define a thread just fine on my starting class (which is declared last). At this stage, the code is just a socket listener which then creates an object of another class to handle each client accepted. Those child objects are supposed to create the threads I need for parallel data capture, encoding and transmission.
The problem is: If I declare a std::thread on my other class, even if exactly like I did on my start class, no matter what, I'm getting this error on build error C2280: 'std::thread::thread(const std::thread &)' : attempting to reference a deleted function [...]\vc\include\functional 1124 1
The only way I was able to workaround this error is to simply not declare a std::thread object in the latter class, which isn't possible, according to what I want it to do...
I'm using VS2013, and my sources are:
stdafx.h
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <Windows.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <thread>
#include <iostream>
#include <vector>
StreamServer.h
#pragma once
#define DEFAULT_BUFLEN 65535
#define DEFAULT_PORT "5649"
class StreamServerClient
{
public:
bool* terminate;
//std::thread client; //If I comment this line out, it builds just fine.
void DoNothing();
StreamServerClient(SOCKET clientSock, bool* ptTerm);
StreamServerClient();
~StreamServerClient();
};
class StreamServer
{
public:
bool terminate;
std::thread Listener;
std::vector<StreamServerClient> clients;
void CreateClient(SOCKET, bool*);
void Listen();
StreamServer();
~StreamServer();
};
StreamServer.cpp
#include "stdafx.h"
#include "StreamServer.h"
StreamServerClient::StreamServerClient(SOCKET clientSock, bool* ptTerm)
{
terminate = ptTerm;
//client = std::thread(&StreamServerClient::DoNothing, this); //Same thing as the declaration
}
StreamServerClient::StreamServerClient()
{
*terminate = false;
//client = std::thread(&StreamServerClient::DoNothing, this); //Same thing as the declaration
}
void StreamServerClient::DoNothing()
{
}
StreamServerClient::~StreamServerClient()
{
}
void StreamServer::Listen()
{
{...}
do {
clients.push_back(StreamServerClient::StreamServerClient(accept(listenSock, NULL, NULL), &terminate));
std::cout << "accepted a client!" << std::endl;
} while (!terminate);
}
StreamServer::StreamServer()
{
terminate = false;
Listener = std::thread(&StreamServer::Listen, this);
Listener.detach();
}
StreamServer::~StreamServer()
{
}
Objects of type std::thread can't be copied. You are best off to just initialize the objects in the member initializer list:
class StreamServerClient
{
public:
bool* terminate;
std::thread client;
void DoNothing();
StreamServerClient(SOCKET clientSock, bool* ptTerm);
StreamServerClient(StreamServerClient&& other);
~StreamServerClient();
};
StreamServerClient::StreamServerClient(SOCKET clientSock, bool* ptTerm)
: terminate(ptTerm)
, client(std::thread(&StreamServerClient::DoNothing, this)) {
}
StreamServerClient::StreamServerClient(StreamServerClient&& other)
: terminate(other.terminate)
, client(std::move(other.client)) {
}
I ommitted the default constructor (note that your version doesn't work because it tries to assign a value to the result of dereferencing an uninitialized pointer) and instead added a move constructor: when pushing back to the std::vector<...> this constructor will be called when providing something which looks like a temporary (i.e., something which either is a temporary or is made to look like one, e.g., using std::move()).
An std::thread object is not copyable. When this line is called:
clients.push_back(StreamServerClient::StreamServerClient(accept(listenSock, NULL, NULL), &terminate));
The StreamServerClient object you create needs to be added to the clients vector, but the only way to do that is by copying it because your StreamServer object does not have a move constructor defined. The default copy constructor for StreamServerClient is generated, and what the default copy constructor in C++11 does is, it calls the copy constructors of all of the data members.
In this case it is calling the copy constructor of the std::thread data member, which is deleted.
The reason std::threads can't be copied is that a std::thread object corresponds to a thread of execution. You should refactor your code, IMO. You could hack together a move constructor for StreamServerClient, but I think there are cleaner solutions, for example, replacing the std::thread with a pointer to std::thread and initializing the thread with a completely separate call.
Edit: In general I would say it is unwise to branch a new thread in an object's contructor, because it is too delicate an operation. (It can fail, then you have to deal with exceptions, etc.) Although probably C++ purists will disagree with me.
Edit: Had stupid terminology.

Cannot lock Qt mutex (QReadWriteLock) Access violation writing

Some background for this question is my previous question:
non-member function pointer as a callback in API to member function (it may well be irrelevant).
The callback launches a thread that writes some data. There is another thread that reads the same data, and that results in some crashes.
I just took a crash course in multi-threading (thanks SO), and here is my attempt to guarantee that the data isn't accessed by the writer and the reader at the same time. I'm using some mutex mechanism from Qt (QReadWriteLock).
#include <QSharedPointer>
#include <QReadWriteLock>
Class MyClass
{
public:
MyClass();
bool open();
float getData();
void streamCB(void* userdata);
protected:
float private_data_;
QSharedPointer<QReadWriteLock> lock_;
};
// callback wrapper from non-member C API to member function void
__stdcall streamCBWrapper(void* userdata)
{
static_cast<MyClass*>(userdata)->streamCB(userdata);
}
// constructor
MyClass::MyClass()
{
lock_ = QSharedPointer<QReadWriteLock>(new QReadWriteLock());
lock_->lockForWrite();
private_data_ = getData();
lock_->unlock();
}
// member callback
void MyClass:streamCB(void* userdata)
{
float a = getData();
lock_->lockForWrite(); //*** fails here
private_data_ = a;
lock_->unlock();
}
I have a segmentation fault while running the program. The VS debugger says Access violation writing location 0x00fedbed. on the line that I marked //*** fails here.
The lock worked in the constructor, but not in the callback.
Any idea what goes wrong? What should I look at? (and how can I refine my question)
Thanks!
Other relevant thread
Cannot access private member declared in class 'QReadWriteLock'Error 1 error C2248: 'QReadWriteLock::QReadWriteLock' (I used the QSharedPointer suggestion)
Edit 1:
The callback is set up
bool MyClass::open()
{
// stuffs
int mid = 0;
set_stream_callback(&streamCBWrapper, &mid);
// more stuffs
return true;
}
Edit 2:
Thank you for all the suggestions.
So my mistake(s) may not be due at all to the mutex, but to my lack of understanding of the API? I'm quite confused.. Here is the API doc for the set_stream_callback.
typedef void (__stdcall *STREAM_CALLBACK)(void *userdata);
/*! #brief Register a callback to be invoked when all subscribed fields have been updated
*
* #param streamCB pointer to callback function
* #param userdata pointer to private data to be passed back as argument to callback
* #return 0 if successful, error code otherwise
*/
__declspec(dllimport) int __stdcall set_stream_callback(
STREAM_CALLBACK streamCB, void *userdata);
Good example why sufficient code example is required.
If I interpret your callback syntax correctly,
set_stream_callback(&streamCBWrapper, &mid);
sets streamCBWrapper as callback function, while &mid is the pointer to userdata.
In the callback, you are actually now casting a pointer to int to MyClass, then try to access a member variable of a non-existant object.
Make sure to pass an instance of MyClass to your callback. I assume this would be this in your case.
Sounds fundamentally like a threading issue to me. Since you're using the Qt mutexing anyway, you might consider using Qt's threading mechanisms and sending signals and slots between the threads. They're pretty well documented and easy to use as long as you follow the suggestions here and here.