Is catching an exception thrown in a loaded shared library portable?
I've noticed that it works with dlfcn.h, but I wonder if this behaviour is in general expected, for example when using LoadLibrary on windows instead?
Example code:
main.cpp:
#include <stdexcept>
#include <cstdio>
#include <dlfcn.h>
typedef void(*dummy_t)();
int main()
{
dummy_t f;
void* handle;
handle = dlopen("module.so", RTLD_LAZY);
f = (dummy_t)dlsym(handle, "modulemain");
try
{
f();
}
catch(std::runtime_error& e)
{
fprintf(stderr, "caught exception: %s\n", e.what());
}
dlclose(handle);
}
module.cpp:
#include <stdexcept>
extern "C" void modulemain()
{
throw std::runtime_error("some terrible error occured");
}
Yes, that should work fine under Windows.
Related
the result of the code below is Unknown error -1.
widget.h:
#ifndef WIDGET_H_
#define WIDGET_H_
#include <memory>
class widget
{
public:
static widget& get_instance();
private:
static std::unique_ptr<widget> instance;
};
#endif
widget.cpp:
#include <mutex>
#include <thread>
#include "class.h"
std::unique_ptr<widget> widget::instance;
std::once_flag is_create;
widget& widget::get_instance()
{
std::call_once(is_create, [=]{ instance = std::make_unique<widget>(); });
return *instance;
}
main.cpp:
#include "widget.h"
#include <iostream>
#include <exception>
int main(int argc, char* argv[])
{
try
{
widget::get_instance();
}
catch (std::system_error e)
{
std::cout << e.what() << std::endl;
}
return 0;
}
this says that
std::system_error if any condition prevents calls to call_once from executing as specified
Is this means make_unique failed ?
I trun to gdb and it seems that something wrong in if (__gthread_active_p ()) line and __gthread_active_ptr == 0. I cannot understand that
why it will throw this exception.
I get this error:
FATAL ERROR:
lua_pcall() failed: error loading module 'foo' from file 'C:\Users\Commander\Desktop\Platform\Debug\foo.dll':
The specified procedure could not be found.
I load my DLL file in Lua:
require("foo")
My DLL code, I use Visual Studio Compiler
(It compiles, no errors)
#include "stdafx.h"
#pragma comment( lib, "liblua53.a" )
extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
#include <iostream>
using namespace std;
extern "C" {
static int l_bar(lua_State *L)
{
puts("l_bar called.");
return 0;
}
void luaopen_foo(lua_State *L)
{
static const struct luaL_Reg foo[] = {
{ "bar", l_bar },
{ NULL, NULL }
};
luaL_newlib(L, foo);
lua_setglobal(L, "foo");
}
}
Is there anyway around this error, Or is it not possible to load dll files in lua
I found the example c++ code here: https://stackoverflow.com/a/12059441/8767704
I am using Windows 8.1, visual studio community 2013.
I downloaded boost 1.59.
I then open Developer Command Prompt for VS2013, run bootstrap.bat, then run b2.exe.
All .lib files are placed under ./stage/lib/.
I set the c++ include path, and linker path. I built my program successfully and run under debug mode.
Here is the error message I get:
Unhandled exception at 0x77394598 in BoostStation.exe: Microsoft C++ exception: boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> > at memory location 0x001BFD74.
Here is the break point:
throw enable_current_exception(enable_error_info(e)); // from throw_exception.hpp
Anyone knows how to solve the problem?
Another question, Are there any .dll files generated by this build and Where can I find them?
Here is my program:
MulticastSender.h
#include <boost/asio.hpp>
#include <boost/scoped_ptr.hpp>
#include <string>
class MulticastSender
{
public:
MulticastSender(const boost::asio::ip::address& multicast_addr, const unsigned short multicast_port)
: ep_(multicast_addr, multicast_port)
{
socket_.reset(new boost::asio::ip::udp::socket(svc_, ep_.protocol()));
}
~MulticastSender()
{
socket_.reset(NULL);
}
public:
void send_data(const std::string& msg)
{
socket_->send_to(boost::asio::buffer(msg), ep_);
}
private:
boost::asio::ip::udp::endpoint ep_;
boost::scoped_ptr<boost::asio::ip::udp::socket> socket_;
boost::asio::io_service svc_;
};
main.cpp
#include "stdafx.h"
#include "MulticastSender.h"
int _tmain(int argc, _TCHAR* argv[])
{
boost::asio::ip::address multiCastGroup;
multiCastGroup.from_string("192.168.32.1");
MulticastSender outDoor(multiCastGroup, 6000);
while (true)
{
outDoor.send_data("Hello");
Sleep(1000);
}
return 0;
}
Your boost installation is ok, because obviously you're able to compile and link a program that throws a boost::exception.
Catch the exception by wrapping your code in a try/catch block, then print out the message. I changed your main-function accordingly:
#include "stdafx.h"
#include "MulticastSender.h"
#include "boost/exception.hpp"
#include <iostream>
int _tmain(int argc, _TCHAR* argv[])
{
try
{
boost::asio::ip::address multiCastGroup;
multiCastGroup.from_string("192.168.32.1");
MulticastSender outDoor(multiCastGroup, 6000);
while (true)
{
outDoor.send_data("Hello");
Sleep(1000);
}
}
catch (const std::exception& e)
{
std::cout << boost::diagnostic_information(e) << std::endl;
}
return 0;
}
This will catch the exception that is thrown by boost and print its message before the program exits.
You should also read up on exceptions in general: http://www.cplusplus.com/doc/tutorial/exceptions/
#include <iostream>
#include <cstring>
#include <dlfcn.h>
#include <fcntl.h>
#include <X11/X.h>
#include <X11/Xlib.h>
void* Module = nullptr;
typedef int (*XNextEventPtr)(Display *display, XEvent *event_return);
XNextEventPtr XNextEventHook = nullptr;
extern "C" int XNextEvent(Display* display, XEvent* event_return)
{
if (event_return)
{
event_return->xany.send_event = false;
}
if (XNextEventHook)
{
return XNextEventHook(display, event_return);
}
return 0;
}
void __attribute__((constructor)) initialize() //DLLMain.
{
char Root[256] = {0};
strcat(Root, "/usr/lib");
#if defined(__x86_64__)
strcat(Root, "/x86_64-linux-gnu");
#else
strcat(Root, "/i386-linux-gnu");
#endif // defined
strcat(Root, "/libX11.so");
Module = dlopen(Root, RTLD_GLOBAL | RTLD_LAZY);
std::cout<<"Loaded"<<std::flush;
XNextEventHook = reinterpret_cast<XNextEventPtr>(dlsym(Module, "XNextEvent")); //some reason RTLD_NEXT didn't find it.
if (XNextEventHook)
{
std::cout<<"Found XNextEvent"<<std::flush;
}
}
void __attribute__((destructor)) deinitialize() //DLLMain.
{
if (Module)
{
dlclose(Module);
Module = nullptr;
}
}
Then I do:
LD_PRELOAD="~/Desktop/MyHook.so" /usr/lib64/firefox
and it will crash. However, it I replace std::cout and std::cerr with printf or perror, it works perfectly!
Is there a reason std::cout would crash the app?
It seems when I load the module using an application written in C++, it loads fine. But if I load the module with an application written in C, it crashes.
Ideas?
But if I load the module with an application written in C, it crashes.
The C application won't have code to call the initialization routines for the C++ library: streams such as std::cout will be uninitialised.
See the FAQ here, specifically:
• You must use your C++ compiler when compiling main() (e.g., for static initialization)
I am trying to access C++ function from C program using Visual Studio 2012 IDE. When I am debugging, I am getting the below error in TestCpp.cpp, in Method: helloworld(), in Line: http_client cli( U("http://localhost:55505/api/Notification"));
Unhandled exception at 0x0000000076D23290 (ntdll.dll) in MyTestCLib.exe: 0xC0000005:
Access violation reading location 0x00000621BC90B128.
Please find the code snippet below.
MyTestCLib.c
#include <ctype.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <my_global.h>
#include <mysql.h>
#include <m_ctype.h>
#include "TestCpp.h"
int main()
{
helloWorld();
return 0;
}
TestCpp.h
#ifndef HEADER_FILE
#define HEADER_FILE
#ifdef __cplusplus
extern "C" {
#endif
void helloWorld();
#ifdef __cplusplus
}
#endif
#endif
TestCpp.cpp
// Calling REST API from C++ using C++ REST API SDK
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
#include <iostream>
#include "TestCpp.h"
using namespace utility; // Common utilities like string conversions
using namespace web; // Common features like URIs.
using namespace web::http; // Common HTTP functionality
using namespace web::http::client; // HTTP client features
using namespace concurrency::streams; // Asynchronous streams
using namespace std;
void helloWorld()
{
http_client cli( U("http://localhost:55505/api/Notification") );
ostringstream_t uri;
uri << U("/PostNotification");
json::value bodyarray = json::value::array();
json::value body = json::value::object();
body[U("TicketNumber")] = json::value::string( U("25868") );
body[U("NotificationMessage")] = json::value::string( U("Test Notification Message") );
bodyarray[0] = body;
http_response response = cli.request( methods::POST, uri.str(), bodyarray.serialize(), U("application/json") ).get();
if ( response.status_code() == status_codes::OK &&
response.headers().content_type() == U("application/json") )
{
json::value json_response = response.extract_json().get();
ucout << json_response.serialize() << endl;
}
else
{
ucout << response.to_string() << endl;
getchar();
}
}
From MyTestCLib.c You call helloWorld declared as C, but complier creates only C++ function version. This call faill because C++ function uses CPU registry and stack different way. There is simple solution. Create C version of function with different name.
TestCpp.h
#ifdef __cplusplus
void helloWorld();
#else
void c_helloWorld();
#endif
TestCpp.cpp
#include "TestCpp.h"
void helloWorld(void)
{
/* cpp code */
}
extern "C" {
void c_helloWorld(void) // C version of helloWorld
{
helloWorld(); // call cpp helloWorld
}
}
Source file with .c extension is complied by C-Compiler. It can't call C++ function. But in .cpp file complied by C++ Compler you can create C function. This "C" function (c_helloWorld) in compiled by C++ compiler and can be called from C-Complier. It can also call C++ function.