MFC DLL: class object value is not persisting throughout the exported call - dll

I have written MFC dll having 3 methods are exported. I have declared class object as global and initialized it in first method then second and third method use and process it.
Issue is that class obeject's value is not getting persisting throughout the file. when second or third method gets call from C# client application, class
object value is getting NULL.
Could anybody tell me why this is happening! I have tried this same scnaerio in another application but this issue is not reproduced.
Code:
Interface File:
#include "StdAfx.h"
#define DLLEXPORT __declspec(dllexport)
using namespace nsAnalyzer;
static CWindowsAnalyzer *pWindowsAnalyzer = NULL;
extern "C" DLLEXPORT void Init( const wchar_t *sCurrentUserDataDir,
const wchar_t *sMachineName,
const wchar_t *sMacId )
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
try
{
nsAnalyzer::CWindowsAnalyzer *pWindowsAnalyzer = new CWindowsAnalyzer( CString(sCurrentUserDataDir),
CString(sMachineName),
CString(sMacId) );
if(pWindowsAnalyzer)
{
pWindowsAnalyzer->Init();
}
}
catch(const std::exception& e)
{
cout<<"Error: Exception occured in Init: "<<e.what()<<endl;
}
}
extern "C" DLLEXPORT bool Analyze()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
bool bResult = false;
try
{
if(pWindowsAnalyzer->ConsolidateRawActivities())
{
cout<<"ConsolidateRawActivities succeed"<<endl;
bResult = true;
}
else
{
cout<<"ConsolidateRawActivities failed"<<endl;
bResult = false;
}
}
catch(const std::exception& e)
{
cout<<"Error: Exception occured in Analyze: "<<e.what()<<endl;
}
return bResult;
}
extern "C" DLLEXPORT void Dispose()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
try
{
// Disponse windows analyzer
if(pWindowsAnalyzer)
{
delete pWindowsAnalyzer;
}
// Dispose Logger
CLogger::DisposeInstance();
}
catch(const std::exception& e)
{
cout<<"Error: Exception occured in Dispose: "<<e.what()<<endl;
}
}

Related

C++/WinRT handling exceptions from StorageFolder::GetFileAsync

When no file exists the app throws an exception which I am unable to catch
In my example code below I create a directory "MyFolder" and save a file "" and save a file "sample.txt" to it.
I then call the function FindFileAsync twice - first using the already created file "sample.txt" which works fine and then using a non-existing file "nofile.txt" which fails with the error
Exception thrown at 0x00007FF94E39D759 in FindFile.exe: Microsoft C++ exception: winrt::hresult_error at memory location.
Is there any solution to this issue.
MainPage.h
#pragma once
#include "MainPage.g.h"
namespace winrt::FindFile::implementation
{
struct MainPage : MainPageT<MainPage>
{
MainPage();
Windows::Foundation::IAsyncAction FindFileAsync(hstring value);
Windows::Foundation::IAsyncAction GetFolderAsync(hstring const& value);
Windows::Foundation::IAsyncAction CreateFileAsync(hstring const& fname);
Windows::Foundation::IAsyncAction DeletefileAsync(Windows::Storage::StorageFile const & value);
void ClickHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& args);
private:
hstring folderDir{ L"MyFolder" };
};
}
namespace winrt::FindFile::factory_implementation
{
struct MainPage : MainPageT<MainPage, implementation::MainPage>
{
};
}
MainPage.cpp
#include "pch.h"
#include "MainPage.h"
#include "MainPage.g.cpp"
using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::UI::Xaml;
using namespace Windows::Storage;
using namespace Windows::Storage::Streams;
using namespace Windows::UI::Popups;
namespace winrt::FindFile::implementation
{
MainPage::MainPage()
{
InitializeComponent();
}
Windows::Foundation::IAsyncAction MainPage::FindFileAsync(hstring value)
{
Windows::Storage::StorageFolder storageFolder{ Windows::Storage::ApplicationData::Current().LocalFolder() };
StorageFolder sampleFolder{ co_await storageFolder.CreateFolderAsync(folderDir, CreationCollisionOption::OpenIfExists) };
try
{
Windows::Storage::StorageFile manifest{ co_await sampleFolder.GetFileAsync(value) };
}
catch (winrt::hresult_error msg)
{
hstring ms{ msg.message() };
MessageDialog dlg(ms, L"File Error");
dlg.ShowAsync();
}
}
Windows::Foundation::IAsyncAction MainPage::GetFolderAsync(hstring const& value)
{
Windows::Storage::StorageFolder storageFolder{ Windows::Storage::ApplicationData::Current().LocalFolder() };
auto sampleFolder{ co_await storageFolder.CreateFolderAsync(value, CreationCollisionOption::OpenIfExists) };
}
IAsyncAction MainPage::CreateFileAsync(hstring const& fname)
{
Windows::Storage::StorageFolder storageFolder{ Windows::Storage::ApplicationData::Current().LocalFolder() };
auto sampleFolder{ co_await storageFolder.CreateFolderAsync(folderDir, CreationCollisionOption::OpenIfExists) };
auto sampleFile{ co_await sampleFolder.CreateFileAsync(L"sample.txt", Windows::Storage::CreationCollisionOption::ReplaceExisting) };
co_await Windows::Storage::FileIO::WriteTextAsync(sampleFile, L"Swift as a shadow");
}
IAsyncAction MainPage::DeletefileAsync(StorageFile const& value)
{
co_await value.DeleteAsync();
}
void MainPage::ClickHandler(IInspectable const&, RoutedEventArgs const&)
{
hstring fname{ L"sample.txt" };
GetFolderAsync(folderDir);
CreateFileAsync(fname);
// The following statement is successful as the file exists
FindFileAsync(fname);
// The following ststement throws an exception error
FindFileAsync(L"nofile.txt");
}
}
In C++/WinRT, some exceptions, but not all, force the debugger to pause program execution despite the exception being handled (thrown inside a try block). However, you can resume it by pressing F5 or launching the app without a debugger (CTRL+F5 or via the start menu). I'm not sure whenever this is a bug or intended behavior.
I have found a solution that worked for me.
When the debugger triggers the exception the message includes a checked checkbox. If unchecked and the program is continued to the end the problem is resolved. When run again the error is not triggered and the catch can handle the "file not found". Not sure why the default setting is to trigger the exception.

Access struct directly of c++ from java code

I am new to javacpp i know java have not much experience in c++. This might be one of very simple question but i am struggling with this. How to access any variable type value written in header of c++ into java code using javacpp. Let us consider example:
C++ Code example:
There is function written in C++ which return the frame of video below is the code for it and expects an Struct argument to be passed.
unsigned char *
Videodecode::getframe_data (void *ptr)
{
GstSample *sample;
GstBuffer *buffer;
GstMapInfo map;
GstCaps *caps;
GstStructure *str;
gint width, height;
gstData *dataa = (gstData *) ptr;
sample = gst_app_sink_pull_sample ((GstAppSink*)dataa->sink);
if (sample != NULL) {
buffer = gst_sample_get_buffer (sample);
gst_buffer_map (buffer, &map, GST_MAP_READ);
if (map.data != NULL) {
caps = gst_sample_get_caps (sample);
if (caps != NULL);
str = gst_caps_get_structure (caps, 0);
if (!gst_structure_get_int (str, "width", &width) ||
!gst_structure_get_int (str, "height", &height)) {
g_print ("No width/height available\n");
}
display_data = map.data;
//displayImg = Mat (Size (width, height ), CV_8UC3, map.data);
// cvtColor (displayImg, displayImg, COLOR_YUV2BGR_YUY2);
gst_buffer_unmap (buffer, &map);
gst_buffer_unref (buffer);
} else
gst_sample_unref (sample);
}
else {
//cout << "gstImageBuffer is NULL" << endl;
return NULL;
}
//return displayImg.data;
return display_data;
}
The structure which need to be passed as argument is below
typedef struct gstData_t
{
GstElement *pipeline;
GstElement *source;
GstElement *demux;
GstElement *parser;
GstElement *decoder;
GstElement *convert;
GstElement *capsfilter;
GstElement *sink;
GstElement *typefind;
} gstData;
Corresponding java code written to access it is below:
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import org.bytedeco.javacpp.FunctionPointer;
import org.bytedeco.javacpp.Loader;
import org.bytedeco.javacpp.Pointer;
import org.bytedeco.javacpp.annotation.Name;
import org.bytedeco.javacpp.annotation.NoOffset;
import org.bytedeco.javacpp.annotation.Platform;
import org.bytedeco.javacpp.annotation.Raw;
import org.bytedeco.javacpp.tools.Builder;
import org.bytedeco.javacpp.tools.ParserException;
#Platform(include = {"Videodecode.h",
},
includepath = {"/usr/include/gstreamer-1.0/","/usr/include/glib-2.0/","/usr/lib/x86_64-linux-gnu/glib-2.0/include/"},
//linkpath = {"/home/ign/git/JavaCppExample/src/main/resources/de/oltzen/javacppexample/"},
link = {"Videodecode"})
public class Videodecode {
NativeVideodecode nda;
static {
Class c = Videodecode.class;
Builder builder = null;
try {
builder = new Builder().classesOrPackages(c.getName());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoClassDefFoundError e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
File[] outputFiles = builder.build();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Loader.load(c);
// Loader.load();
}
public Videodecode() {
nda = new NativeVideodecode();
}
public Videodecode(String filename) {
nda = new NativeVideodecode(filename);
}
public boolean filePathCpp(String str){
return nda.filePathCpp(str);
}
public boolean settingValCpp(String str){
return nda.settingValCpp(str);
}
public boolean process_event (int event) {
return nda.process_event(event);
}
public java.nio.ByteBuffer test1122 (String buffer) {
return nda.test1122(buffer);
}
public java.nio.ByteBuffer test112233 (String buffer) {
return nda.test1122(buffer);
}
public java.nio.ByteBuffer getframe_data(java.nio.ByteBuffer buffer){
return nda.getframe_data(buffer);
}
public Pointer gstData(){
return nda.gstData();
}
#Name("Videodecode")
public static class NativeVideodecode extends Pointer {
static {
Loader.load();
}
public NativeVideodecode() {
allocate();
}
public NativeVideodecode(String filename) {
System.out.println("filename "+filename);
allocate(filename);
}
public NativeVideodecode(Pointer p) {
super(p);
}
private native void allocate(String filename);
private native void allocate();
private native boolean filePathCpp(String str);
private native boolean settingValCpp(String str);
private native boolean process_event(int event);
private native java.nio.ByteBuffer test1122(String buffer);
private native java.nio.ByteBuffer test112233(String buffer);
// private native boolean test1122(byte[] buffer);
private native java.nio.ByteBuffer getframe_data (java.nio.ByteBuffer buffer);
#NoOffset private native Pointer gstData();
}
}
Problems being faced by me :
How to access Struct from C++ and pass it as an argument using java.
How to access frame data which is unsigned char*.
Approach which i tried to perform this.
To access Struct, i tried using offsetof but not sure how to use it in javacpp.
To access frame data i tried using java.nio.ByteBuffer but seems its not working properly.
While trying to compile code using mvn clean install below error is getting triggered.
[INFO] --- javacpp:1.3:build (javacpp.compiler) # projecustom ---
[INFO] Detected platform "linux-x86_64"
[INFO] Building for platform "linux-x86_64"
[WARNING] Could not load platform properties for class com.proje.decoder.connectorJavaCpp
[WARNING] Could not load platform properties for class com.proje.decoder.test1234
[INFO] Generating /home/ign/eclipse-workspace/projecustom/target/classes/com/proje/decoder/jniVideodecode.cpp
[INFO] Compiling /home/ign/eclipse-workspace/projecustom/target/classes/com/proje/decoder/linux-x86_64/libjniVideodecode.so
[INFO] g++ -I/usr/include/gstreamer-1.0/ -I/usr/include/glib-2.0/ -I/usr/lib/x86_64-linux-gnu/glib-2.0/include/ -I/usr/lib/jvm/java-8-openjdk-amd64/include -I/usr/lib/jvm/java-8-openjdk-amd64/include/linux /home/ign/eclipse-workspace/projecustom/target/classes/com/proje/decoder/jniVideodecode.cpp -march=x86-64 -m64 -O3 -s -Wl,-rpath,$ORIGIN/ -Wl,-z,noexecstack -Wl,-Bsymbolic -Wall -fPIC -shared -o libjniVideodecode.so -lVideodecode
/home/ign/eclipse-workspace/projecustom/target/classes/com/proje/decoder/jniVideodecode.cpp: In function ‘_jobject* Java_com_proje_decoder_Videodecode_00024NativeVideodecode_gstData(JNIEnv*, jobject)’:
/home/ign/eclipse-workspace/projecustom/target/classes/com/proje/decoder/jniVideodecode.cpp:1532:21: error: ‘class Videodecode’ has no member named ‘gstData’
rptr = ptr->gstData();
edit:
let me try to take one simple example :
C++ Code:
#include <stdio.h>
struct test
{
int a;
std::string b;
};
class Foo {
public:
int n;
int m=70;
test tst;
// tst.a=10;
// tst.b="hi";
Foo(int n) : n(n) { }
virtual ~Foo() { }
virtual void bar() {
printf("Callback in C++ (n == %d)\n", n);
}
};
void callback(Foo *foo) {
foo->bar();
}
is it possible to write modify java code below to access a and b variables of struct
package com.ign.examples;
import org.bytedeco.javacpp.*;
import org.bytedeco.javacpp.annotation.*;
#Platform(include="Foo.h")
public class VirtualFoo1 {
static { Loader.load(); }
public static class Foo extends Pointer {
static { Loader.load(); }
public Foo(int n) { allocate(n); }
private native void allocate(int n);
#NoOffset public native int n(); public native Foo n(int n);
#Virtual public native void bar();
public native int m(); public native void m(int m);
// public native #Cast("int") int a(); public native Foo a(int a);
public native Pointer tst(); public native void tst(Pointer tst);
}
public static native void callback(Foo foo);
public static void main(String[] args) {
Foo foo = new Foo(13);
System.out.println(foo.m());
}
}

Call c++ code in c# by a cli wrapper

I have a c++ code that needs to be called in c# by a cli wrapper. I am stuck at the operator overloading part.
//this is my code
//Cppclass.h
#ifdef CPP_EXP_EXPORTS
#define CPP_EXP __declspec(dllexport)
#else
#define CPP_EXP __declspec(dllimport)
#endif
class CPP_EXP Cppclass;
CPP_EXP Cppclass operator-(Cppclass const &, Cppclass const &);
class CPP_EXP Cppclass
{
public:
friend CPP_EXP Cppclass operator-(Cppclass const &, Cppclass const &);
};
//this is my managed c++ code.
#include "Cppclass.h"
namespace Wrapper
{
public ref class cppwrapclass
{
public:
static cppwrapclass ^ operator-(cppwrapclass%A,cppwrapclass%B)
{
operator-(A.obj,B.obj);
return gcnew cppwrapclass();
}
private:
Cppclass *obj;
};
}
Its showing an intellisense error and not getting compiled.
You write a wrapper like this:
public ref class cppwrapclass
{
public:
cppwrapclass(Cppclass *obj)
: obj(obj)
{
}
~cppwrapclass()
{
this->!cppwrapclass();
}
!cppwrapclass()
{
if (obj)
{
delete obj;
obj = nullptr;
}
}
static cppwrapclass^ operator-(cppwrapclass% A, cppwrapclass% B)
{
return gcnew cppwrapclass(new Cppclass(*A.obj - *B.obj));
}
private:
Cppclass* obj;
};
A.obj is of type Cppclass*, therefore *A.obj is of type Cppclass, and *A.obj - *B.obj is a temporary Cppclass which needs to be moved to the heap in order to be referenced by the wrapper, hence the copy constructor call: new Cppclass(*A.obj - *B.obj).
The rest is the Dispose pattern and finalizer plumbing code.

Immediate Access Violation when debugging Windows.Devices.Sensors project in Windows 7

I have a large solution with 50+ unmanaged projects in it. I have recently added a project with managed code in it to the solution. The managed code accesses Windows.Devices.Sensors in a .NET dll. This dll is eventually wrapped by unmanaged code and called from another unmanaged project.
My problem is that I get the following access violation before main() even executes.
Unhandled exception at 0x744b8ea0 in myApplication.exe: 0xC0000005: Access violation.
Managed code:
#using <Windows.winmd>
using namespace Windows::Devices::Sensors;
#include <math.h>
namespace TabletSensors
{
namespace NET
{
public ref class DotNetDllClass
{
public:
DotNetDllClass()
{
Initialization();
}
~DotNetDllClass()
{
}
float* GetQuaternion()
{
OrientationSensorReading^ reading = _orientation->GetCurrentReading();
if( reading != nullptr )
{
float* quat = new float[4];
quat[0] = reading->Quaternion->X;
quat[1] = reading->Quaternion->Y;
quat[2] = reading->Quaternion->Z;
quat[3] = reading->Quaternion->W;
return quat;
}
else
{
return NULL;
}
}
private:
void Initialization()
{
_orientation = OrientationSensor::GetDefault();
if( _orientation != nullptr )
{
_orientation->ReportInterval = 16;
}
else
{
// not good ... throw exception or something
}
}
OrientationSensor^ _orientation;
};
}
}
Wrapper header file:
namespace TabletSensors
{
namespace NETWrapper
{
class DLLEXPORT_SENSORS WrapperClass
{
public:
__stdcall WrapperClass();
__stdcall ~WrapperClass();
float* __stdcall GetQuaternion();
};
}
}
Wrapper cpp file:
#define MIXSENSORS_BUILD
#include <gcroot.h>
#include "DotNetWrapper.h"
#include "DotNetDll.h"
using namespace TabletSensors::NETWrapper;
using namespace TabletSensors::NET;
static gcroot<TabletSensors::NET::DotNetDllClass^> Sensors = nullptr;
static System::UInt16 refCount = 0;
#pragma managed
inline TabletSensors::NET::DotNetDllClass^ GetSensors(void)
{
return (TabletSensors::NET::DotNetDllClass^)Sensors;
}
void Init()
{
++refCount;
if(GetSensors() == nullptr)
{
Sensors = gcnew TabletSensors::NET::DotNetDllClass();
}
}
void CleanUp()
{
if( refCount > 0 )
{
--refCount;
}
}
float* GetQuaternion_()
{
return Sensors->GetQuaternion();
}
#pragma unmanaged
TabletSensors::NETWrapper::WrapperClass::WrapperClass()
{
Init();
}
TabletSensors::NETWrapper::WrapperClass::~WrapperClass()
{
CleanUp();
}
float* TabletSensors::NETWrapper::WrapperClass::GetQuaternion()
{
float* x = new float[4];
return GetQuaternion_();
}
#pragma managed
Unmanaged project referencing my wrapper class:
#include "DotNetWrapper.h"
.
.
.
void UnmanagedProject::Update()
{
// if this line is present, I get an access violation without hitting any breakpoints.
TabletSensors::NETWrapper::WrapperClass _tabletSensors;
.
.
.
}
Since the managed code is trying to access Tablet Sensors I understand why it doesn't work on my Windows 7 desktop. What I don't understand it why it won't even allow me to debug my code at all. No breakpoints are hit before the Access Violation occurs.
What I would really like to figure out is how to use exception handling or #ifdefs to keep this crash from happening. But I have had very little luck.
Any ideas?
The fix is to Delay Load the managed DLL. The allows the application to run until that DLL is explicitly called. Thanks to Ben Voight for his answer here: https://stackoverflow.com/a/28467701/1454861

Gibberish coming from ASIO SSL Server code after the first message

I'm trying to write a SSL-based async server using Boost ASIO example code from here.
I get the first message and its response correctly at the client side. Then, I send a second message which is received fine at the server, however when the response is sent to client. It comes as some gibberish.
I have uploaded the server code to pastebin. Also, find it below:
// file - Server.h
class Server
{
public:
explicit Server(const std::string &address,
int port,
std::size_t threadPoolSize);
// run the io_service loop
void run();
// stop the server
void stop();
private:
//handle async accept operation
void handleAccept(const boost::system::error_code &e);
// number of threads in thread pool
std::size_t _threadPoolSize;
// the io_service
boost::asio::io_service _ioService;
// acceptor to listen for incoming connections
boost::asio::ip::tcp::acceptor _acceptor;
std::string get_password()
{
return "password";
}
// ssl context
boost::asio::ssl::context _context;
ConnectionPtr _connection;
};
//////////////////////////////////////////////////////////////////////////
// file - Server.cpp
//////////////////////////////////////////////////////////////////////////
Server::Server(const std::string& address,
int port,
std::size_t threadPoolSize)
: _threadPoolSize(threadPoolSize),
_acceptor(_ioService),
_context(_ioService, boost::asio::ssl::context::sslv23),
_connection()
{
try {
DEBUG_2("Starting server on port: ", port);
boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port);
_acceptor.open(endpoint.protocol());
_acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
_acceptor.bind(endpoint);
_acceptor.listen();
_context.set_options(
boost::asio::ssl::context::default_workarounds
| boost::asio::ssl::context::no_sslv2
| boost::asio::ssl::context::single_dh_use);
_context.set_password_callback(boost::bind(&Server::get_password, this));
_context.use_certificate_chain_file("./demoCA/cacert.pem");
_context.use_private_key_file("./demoCA/private/cakey.pem",
boost::asio::ssl::context::pem);
// _context.use_tmp_dh_file("dh512.pem");
_connection.reset(new CclConnection(_ioService, _context));
_acceptor.async_accept(_connection->socket(),
boost::bind(&Server::handleAccept,
this,
boost::asio::placeholders::error));
}
catch(std::exception& e)
{
STD_EXCEPTION_MESSAGE;
throw;
}
}
void Server::run()
{
// Create a pool of threads to run all of the io_services.
std::vector<boost::shared_ptr<boost::thread> > threads;
for (std::size_t i = 0; i < _threadPoolSize; ++i)
{
boost::shared_ptr<boost::thread>
thread(new boost::thread(
boost::bind(&boost::asio::io_service::run,
&_ioService)
)
);
threads.push_back(thread);
}
// Wait for all threads in the pool to exit.
for (std::size_t i = 0; i < threads.size(); ++i)
threads[i]->join();
}
void Server::stop()
{
_ioService.stop();
}
void Server::handleAccept(const boost::system::error_code& e)
{
if (!e)
{
_connection->handshake();
_connection.reset(new CclConnection(_ioService, _context));
_acceptor.async_accept(_connection->socket(),
boost::bind(&Server::handleAccept,
this,
boost::asio::placeholders::error));
}
}
////////////////////////////////////////////////////////////
// file - Connection.h
////////////////////////////////////////////////////////////
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
typedef boost::asio::ssl::stream< boost::asio::ip::tcp::socket >
ssl_socket;
class Connection
: public boost::enable_shared_from_this<Connection>
{
public:
explicit Connection(boost::asio::io_service& io_service,
boost::asio::ssl::context& context);
//get socket from the connection
ssl_socket::lowest_layer_type& socket();
// do an SSL handshake
void handshake();
//get socket from the connection
boost::asio::io_service::strand& strand();
// start first async operation
void start();
void sendResponse(const Response& response);
void close();
// get remote IP address for this connection
std::string getIPAddress();
private:
void handleRead(const boost::system::error_code& e,
std::size_t bytesTransferred);
void handleWrite(const boost::system::error_code& e);
boost::asio::io_service::strand _strand;
ssl_socket _socket;
void handleHandshake(const boost::system::error_code& e);
boost::array<char, 8192> _buffer;
};
typedef boost::shared_ptr<Connection> ConnectionPtr;
///////////////////////////////////////////////////////////////
// File - Connection.cpp
///////////////////////////////////////////////////////////////
Connection::Connection(boost::asio::io_service& io_service,
boost::asio::ssl::context& context)
: _strand(io_service),
_socket(io_service, context)
{
}
ssl_socket::lowest_layer_type& Connection::socket()
{
return _socket.lowest_layer();
}
boost::asio::io_service::strand& Connection::strand()
{
return _strand;
}
void Connection::start()
{
_socket.async_read_some(boost::asio::buffer(_buffer),
_strand.wrap(
boost::bind(
&Connection::handleRead,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
)
);
}
void Connection::handshake()
{
std::cout << "doing ssl handshake" << std::endl;
_socket.async_handshake(boost::asio::ssl::stream_base::server,
_strand.wrap(
boost::bind(
&Connection::handleHandshake,
shared_from_this(),
boost::asio::placeholders::error
)
)
);
}
void Connection::handleHandshake(const boost::system::error_code& error)
{
if (!error)
{
_socket.async_read_some(boost::asio::buffer(_buffer),
_strand.wrap(
boost::bind(
&Connection::handleRead,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
)
);
}
else
{
std::cout << "error occured: " << error.message();
this->close();
}
}
void Connection::handleRead(const boost::system::error_code& e,
std::size_t bytesTransferred)
{
if (!e) {
// handle read data
this->start();
}
else {
this->close();
}
}
void Connection::handleWrite(const boost::system::error_code& e)
{
if (!e) {
this->start();
}
else {
this->close();
}
}
void Connection::sendResponse(const Response& response)
{
boost::asio::async_write(_socket,
boost::asio::buffer(convertToString(response)),
_strand.wrap(
boost::bind(
&Connection::handleWrite,
shared_from_this(),
boost::asio::placeholders::error
)
)
);
}
void Connection::close()
{
boost::system::error_code ignoredCode;
socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both,
ignoredCode);
}
std::string Connection::getIPAddress()
{
return socket().remote_endpoint().address().to_string();
}
Can someone point me out as to what is being done wrongly here?
Update: The issue is resolved as noted by me in the comment. The issue was exactly similar to another old question on stackoverflow.
Your code doesn't recognize, that boost::asio::buffer is only the wrapper for objects from which it was constructed.
Here (in Connection::sendResponse):
boost::asio::buffer(convertToString(response))
You created buffer out of a (probably) temporary object, which was destroyed before it was used by boost::asio::async_write.
Boost.Asio documentation specifically tells you about that in the paragraph "Buffer invalidation"
For the boost::asio::buffer overloads that accept an argument of type
std::string, the buffer objects returned are invalidated according to
the rules defined for invalidation of references, pointers and
iterators referring to elements of the sequence (C++ Std, 21.3).