Propagating exceptions in C++ Builder threads - exception

Based on the credited answer to How can I propagate exceptions between threads?, I created a little test application to explore propagation:
#include <vcl.h>
#pragma hdrstop
#include<iostream>
#include<thread>
#include<exception>
#include<stdexcept>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
static std::exception_ptr teptr = nullptr;
static UnicodeString status;
void __fastcall f()
{
try
{
throw std::runtime_error("To be passed between threads");
} catch(...) {
teptr = std::current_exception();
if (!teptr) {
status += U"; NULL teptr";
} else {
status += U"; Non-NULL teptr";
}
}
}
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
std::thread mythread(f);
mythread.join();
std::this_thread::sleep_for(std::chrono::seconds(3));
if (teptr) {
status += U"; Button1Click non-NULL teptr";
try
{
std::rethrow_exception(teptr);
} catch(const std::exception &ex) {
std::cerr << L"Thread exited with exception: " << ex.what() << "\n";
}
} else {
status += U"; Button1Click NULL teptr";
}
Application->MessageBox(status.c_str(), L"Button1Click", MB_OK);
}
The results in the message box turn out to be "; NULL teptr; Button1Click NULL teptr", so to me, it looks like std::current_exception() failed to work. How can I get an application-thrown error to propagate back to the program that launched the thread?

Related

Arduino UART ESP01 , json parse 4with 433 MHZ receiver and transmitter

I am using 2 Arduino, 1 Esp01,433 MHz 1 receiver and 1 433 MHz transmitter. The transmtiter sending uint_8 "85648217". When i write below the code.I can receive the messages and i can get response from api.
#include <ArduinoJson.h>
#include <RH_ASK.h>
#include <SPI.h>
#define RX 0
#define TX 1
using namespace std;
unsigned char rxBuf[512];
RH_ASK rf_driver;
void setup() {
rf_driver.init();
Serial.begin(9600);
}
void loop() {
{
uint8_t buf[8];
uint8_t buflen = sizeof(buf);
if (rf_driver.recv(buf, &buflen))
{
Serial.println("https://example.com/example/example/"+(String((char*)buf))+";headers\n");
//(String((char*)buf) is number from transmitter
String message = Serial.readString();
const size_t capacity = JSON_OBJECT_SIZE(1) + 20;
DynamicJsonDocument doc(capacity);
// DeserializationError error = deserializeJson(doc, message);
//if (error) {
// Serial.print(F("deserializeJson() failed: "));
//Serial.println(error.f_str());
// return;
// }
Serial.println(doc["attribute"].as<const char*>());
Serial.println(message);
}
}
}
When i write code like this.I can't receive message.I am receving "07413943⸮" or "07413943⸮ " .I don't know why is this happening.Does anyone know how can i fix this?
#include <ArduinoJson.h>
#include <RH_ASK.h>
#include <SPI.h>
#define RX 0
#define TX 1
using namespace std;
unsigned char rxBuf[512];
RH_ASK rf_driver;
void setup() {
rf_driver.init();
Serial.begin(9600);
}
void loop() {
{
uint8_t buf[8];
uint8_t buflen = sizeof(buf);
if (rf_driver.recv(buf, &buflen))
{
Serial.println("https://example.com/example/example/"+(String((char*)buf))+";headers\n");
//(String((char*)buf) is number from transmitter
String message = Serial.readString();
const size_t capacity = JSON_OBJECT_SIZE(1) + 20;
DynamicJsonDocument doc(capacity);
DeserializationError error = deserializeJson(doc, message);
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str());
return;
}
Serial.println(doc["attribute"].as<const char*>());
Serial.println(message);
}
}
}
I found the solution.It seems like i need to convert string this (String((char*)buf)) but not like this.Here is how i solved.
uint8_t buflen = sizeof(buf)
if (rf_driver.recv(buf, &buflen))
{
rf_driver.printBuffer("Got:",buf,buflen);
String rcv;
for (int i=0; i<buflen;i++){
rcv+=(char)buf[i];
}
Serial.print("example.com/example"+rcv+";header");
String input = Serial.readString();
StaticJsonDocument<32> doc;
DeserializationError error = deserializeJson(doc,input);
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str());
return;
}
float attribute= doc["attribute"]; // 428.5
Serial.println(float(attribute));
Serial.println(input);

How can I get my queue in C++ work? Unhandeled Exception: Access violation reading location

I got a problem by implementing a queue in C++. I looked for similar problems, but didn't find anything usefull.
I'm using Visual Studio 2019.
I seperated my program in a Main.cpp, a Queue.h and Queue.cpp, Patient.h and Patient.cpp.
I tried to convert the concept for this from Java to C++, but I just can't find a solution for my function getInfo().
I get an exception like this:
Unhandled exception at 0x7C0EF3BE (ucrtbased.dll) in Queue.exe: 0xC0000005: Access violation reading location 0xE8884D8D.
Would be nice if anyone could help me with my problem and explain what I did wrong.
I'm just a beginner so don't be too harsh on me pls xD
Main.cpp:
#include "Queue.h"
#include "Patient.h"
int main() {
Queue queue;
Patient patient1("Name1");
Patient patient2("Name2");
queue.add(patient1);
queue.add(patient2);
queue.getInfo();
}
Queue.h:
#pragma once
#include <iostream>
#include "Patient.h"
using namespace std;
class Queue {
private:
Patient* beginning;
Patient* end;
int amount;
public:
Queue();
void add(Patient p);
Patient remove();
void getInfo();
};
Queue.cpp:
#include "Queue.h"
Queue::Queue() {
beginning = 0;
end = 0;
amount = 0;
}
void Queue::add(Patient p) {
if (amount == 0) {
beginning = &p;
end = &p;
} else {
end->setFollower(p);
end = &p;
}
amount++;
}
Patient Queue::remove() {
if (amount == 0) {
cout << "You can't remove a patient. The Queue is empty!" << endl;
} else {
*beginning = beginning->getFollower();
amount--;
}
return *beginning;
}
void Queue::getInfo() {
if (amount == 0) {
cout << "The Queue is empty!" << endl;
} else {
cout << "There are " << amount << " Patients in the Queue!" << endl;
cout << "The following list provides all Patients in the Queue-order:" << endl;
beginning->getInfo();
}
}
Patient.h:
#pragma once
#include <iostream>
#include <string>
using namespace std;
class Patient {
private:
string name;
Patient* follower;
string* nameptr;
public:
Patient(string newname);
void setFollower(Patient p);
Patient getFollower();
void getInfo();
};
Patient.cpp:
#include "Patient.h"
Patient::Patient(string newname) {
name = newname;
follower = 0;
nameptr = &name;
}
void Patient::setFollower(Patient p) {
follower = &p;
}
Patient Patient::getFollower() {
return *follower;
}
void Patient::getInfo() {
cout << *nameptr << endl;
if (follower == 0) {
cout << "No follower existing!" << endl;
}
else {
follower->getInfo();
}
cin.get();
}
There are a few places where you mix up passing by value with passing by reference.
To start with, the first problem is here:
void Queue::add(Patient p) {
if (amount == 0) {
beginning = &p;
end = &p;
} else {
end->setFollower(p);
end = &p;
}
amount++;
}
You are passing the value of Patient p rather than a reference to the actual object. To fix this you only need to add an "&" to your functional call like this:
void Queue::add(Patient& p) {
if (amount == 0) {
beginning = &p;
end = &p;
} else {
end->setFollower(p);
end = &p;
}
amount++;
}
Note the "&" in the parameters list. Then you must also update the function header:
class Queue {
private:
Patient* beginning;
Patient* end;
int amount;
public:
Queue();
void add(Patient& p);
Patient remove();
void getInfo();
};
You must also pass by reference for your setFollower function:
void Patient::setFollower(Patient& p) {
follower = &p;
}
and in the header file:
void setFollower(Patient& p);
What you need to know going forward is that in C++ all arguments are passed by value unless you specify passing by reference in the function's parameter list. Here is an article about passing variables to functions if you'd like to read more (https://iq.opengenus.org/call-by-value-vs-call-by-reference-cpp/).

DirectX DrawText doesn't work

I have been learning DirectX and Windows programming for a short time now. However, I have a problem with the DirectX function DrawText. Somehow it doesn't display text in the window, and cannot figure out why. Here is my code:
main.cpp
//Include's
#include"winwindow.hpp"
#include<time.h>
#include<iostream>
//main
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow){
c_winwindow window(hInstance,nCmdShow);
bool b_init=false;
b_init=window.init();
while(b_init){
window.clear(D3DCOLOR_XRGB(0xEF,0xEF,0xEF));
window.drawtext(0,0,L"Halo",D3DCOLOR_COLORVALUE(0xFF,0,0,0xFF));
window.display();
b_init=window.update();
}
return 0;
}
winwindow.hpp
//Include's
#include"windows.h"
#include"d3d9.h"
#include"d3dx9.h"
//c_winwindow
class c_winwindow{
private:
HWND hwnd;
MSG msg;
HINSTANCE hInstance;
int nCmdShow;
bool b_init;
static LRESULT CALLBACK Messagehandler(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
LPDIRECT3D9 lpd3d;
LPDIRECT3DDEVICE9 lpd3ddevice;
ID3DXFont *p_d3dfont;
bool initwin();
bool initdx();
public:
c_winwindow(const HINSTANCE &hInstance,int nCmdShow);
~c_winwindow();
bool init();
bool update();
void clear(D3DCOLOR clr);
void display();
void drawtext(unsigned short int,unsigned short int,LPCWSTR,D3DCOLOR);
};
winwindow.cpp
//Include's
#include"winwindow.hpp"
#include<iostream>
//c_winwindow memberfunction's
//konstruktor
c_winwindow::c_winwindow(const HINSTANCE &temphInstance,int tempnCmdShow){
hInstance=temphInstance;
nCmdShow=tempnCmdShow;
hwnd=NULL;
lpd3d=NULL;
lpd3ddevice=NULL;
b_init=false;
}
//destruktor
c_winwindow::~c_winwindow(){
PostQuitMessage(0);
hwnd=NULL;
if(lpd3d!=NULL){
lpd3d->Release();
lpd3d=NULL;
}
if(lpd3ddevice!=NULL){
lpd3ddevice->Release();
lpd3ddevice=NULL;
}
if(p_d3dfont!=NULL){
p_d3dfont->Release();
p_d3dfont=NULL;
}
}
//initwin
bool c_winwindow::initwin(){
if(!b_init){
WNDCLASS wc;
ZeroMemory(&wc,sizeof(wc));
wc.lpfnWndProc=Messagehandler;
wc.hInstance=hInstance;
wc.lpszClassName=L"wndc";
RegisterClass(&wc);
hwnd=CreateWindow(L"wndc",L"TestWindow",WS_SYSMENU,10,10,1200,800,NULL,NULL,hInstance,NULL);
if(hwnd==NULL){
std::cout << "failed to create Window!" << std::endl;
return false;
}else{
b_init=true;
ShowWindow(hwnd,nCmdShow);
return true;
}
}else{
return true;
}
}
//initdx
bool c_winwindow::initdx(){
lpd3d=Direct3DCreate9(D3D_SDK_VERSION);
if(lpd3d==NULL){
std::cout << "couldn't create direct3d Object" << std::endl;
return false;
}
D3DPRESENT_PARAMETERS params;
ZeroMemory(&params,sizeof(params));
params.SwapEffect=D3DSWAPEFFECT_FLIP;
params.hDeviceWindow=hwnd;
params.Windowed=true;
params.BackBufferWidth=1200;
params.BackBufferHeight=800;
params.BackBufferFormat= D3DFMT_A8R8G8B8;
if(FAILED(lpd3d->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hwnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING,&params,&lpd3ddevice))){
std::cout << "couldn't create direct3d device" << std::endl;
return false;
}
if(D3D_OK!=D3DXCreateFont(lpd3ddevice,22,0,FW_NORMAL,1,false,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,ANTIALIASED_QUALITY,DEFAULT_PITCH|FF_DONTCARE,L"Arial",&p_d3dfont)){
std::cout << "couldn't create font" << std::endl;
return false;
}
return true;
}
//init
bool c_winwindow::init(){
return initwin()&&initdx();
}
//update
bool c_winwindow::update(){
if(b_init){
if(GetMessage(&msg,NULL,0,0)){
TranslateMessage(&msg);
DispatchMessage(&msg);
return true;
}else{
if(lpd3d!=NULL){
lpd3d->Release();
lpd3d=NULL;
}
if(lpd3ddevice!=NULL){
lpd3ddevice->Release();
lpd3ddevice=NULL;
}
hwnd=NULL;
b_init=false;
return false;
}
}else{
return false;
}
}
//clear
void c_winwindow::clear(D3DCOLOR clr){
lpd3ddevice->Clear(0,0,D3DCLEAR_TARGET,clr,0,0);
lpd3ddevice->BeginScene();
}
//display
void c_winwindow::display(){
lpd3ddevice->EndScene();
lpd3ddevice->Present(0,0,0,0);
}
void c_winwindow::drawtext(unsigned short int us_x,unsigned short int us_y,LPCWSTR text,D3DCOLOR textcolor){
RECT r;
SetRect(&r,us_x,us_y,0,0);
p_d3dfont->DrawText(NULL,text,-1,&r,DT_LEFT,textcolor);
}
//WndProc
LRESULT CALLBACK c_winwindow::Messagehandler(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam){
switch(msg){
case(WM_DESTROY):
PostQuitMessage(0);
return 0;
break;
case(WM_PAINT):
return 0;
break;
}
return DefWindowProc(hwnd,msg,wParam,lParam);
}
The window appears grey, with no text in it. Can anyone explain why there is no text?

private C++ template function in a regular class - OpenCL

I am trying to create a customized class around the OpenCL C++ wrapper to get some specific information from the available devices. For example get the number of available GPUs, CPUs, etc. in a platform. To reduce code I decided to implement a private template function as shown below:
//Devices.hpp
class Devices
{
public:
Devices(const cl::Platform& inputPlatform)
{
inputPlatform.getDevices(CL_DEVICE_TYPE_ALL, &availableDevices);
}
cl_int getTotalNumberOfDevices()
{
return availableDevices.size();
}
cl_int getTotalNumberOfGPUs()
{
return countDevicesWithSpecificProperty(CL_DEVICE_TYPE, CL_DEVICE_TYPE_GPU);
}
private:
std::vector<cl::Device> availableDevices;
template <typename T>
cl_int countDevicesWithSpecificProperty(
const cl_device_info& deviceInfo,
const T& searchPropertyValue)
{
cl_int totalNumberOfDevices = getTotalNumberOfDevices();
T response;
cl_int count = 0;
for (cl_int i = 0; i < totalNumberOfDevices; ++i)
{
try
{
availableDevices.at(i).getInfo(deviceInfo, &response);
}
catch (cl::Error e)
{
return e.err();
}
if (response == searchPropertyValue) ++count;
}
return count;
}
};
While the code compiles correctly, getInfo throws a CL_INVALID_VALUE error. When I implemented the same code using regular function (instead of a template) the code works fine:
//Devices.hpp
class Devices
{
public:
Devices(const cl::Platform& inputPlatform)
{
inputPlatform.getDevices(CL_DEVICE_TYPE_ALL, &availableDevices);
}
cl_int getTotalNumberOfDevices()
{
return availableDevices.size();
}
cl_int getTotalNumberOfGPUs()
{
return countDevicesWithSpecificProperty(CL_DEVICE_TYPE, CL_DEVICE_TYPE_GPU);
}
private:
std::vector<cl::Device> availableDevices;
cl_int countDevicesWithSpecificProperty
(const cl_device_info& deviceInfo,
const cl_device_type& searchPropertyValue)
{
cl_int totalNumberOfDevices = getTotalNumberOfDevices();
cl_device_type response;
cl_int count = 0;
for (cl_int i = 0; i < totalNumberOfDevices; ++i)
{
try
{
availableDevices.at(i).getInfo(deviceInfo, &response);
}
catch (cl::Error e)
{
return e.err();
}
if (response == searchPropertyValue) ++count;
}
return count;
}
};
Any thoughts?
PS: The method is invoked as follows:
//main.cpp
#define __CL_ENABLE_EXCEPTIONS
#include <iostream>
#include <vector>
#include <CL/cl.hpp>
#include "Devices.hpp"
int main()
{
try
{
std::vector<cl::Platform> availablePlatforms;
cl::Platform::get(&availablePlatforms);
Devices d(availablePlatforms[0]);
std::cout << d.getTotalNumberOfGPUs() << std::endl;
}
catch (cl::Error e)
{
std::cout << e.what() << std::endl << e.err() << std::endl;
}
return 0;
}
The issue is that your response variable doesn't have the correct type in your templated version. This is because you are passing CL_DEVICE_TYPE_GPU to the templated parameter, which is a preprocessor macro, and so won't necessarily have the correct type needed for the device info query.
One solution is to explicitly cast the templated parameter to ensure it has the correct type:
return countDevicesWithSpecificProperty(CL_DEVICE_TYPE, (cl_device_type)CL_DEVICE_TYPE_GPU);
Check assembler listing for both cases. There should be some difference in what compiler generates.

non-portable way to find exception type in catch (...) for g++

Related questions:
Determining exception type after the exception is caught?
How can I determine the current exception in a catch (...) block?
This question differs because I don't care about portability. I'm interested in code specifically for g++ or perhaps even specific versions of g++ (4.6.3). It will not be used in production.
I'm dealing with legacy code that has thousands of throw statements with perhaps hundreds of thrown types. This code runs on nearly 1000 machines and catches about 40 throws per day. It is not repeatable.
At the outside layer, I can do a try { /.../ } catch (...) { /* caught it */ } and see that an exception was thrown. But I have not been able to find the type of the exception, let alone the location it is thrown from.
I believe the information must be available because code like the following works and prints "Y":
#include <iostream>
using namespace std;
struct X {};
struct Y {};
struct Z {};
int main(int, char **) {
try {
//...
throw Y();
//...
} catch (...) {
cout << "Caught unknown" << endl;
try {
throw;
} catch (const X &x) {
cout << "X" << endl;
} catch (const Y &y) {
cout << "Y" << endl;
} catch (const Z &z) {
cout << "Z" << endl;
}
}
}
Are there any [non-portable|dirty|nasty|ugly]* tricks to identify the exception type under g++ in a catch (...)?
Here's what I use:
#include <cxxabi.h>
using std::string;
string deMangle(const char* const name)
{
int status = -1;
char* const dem = __cxxabiv1::__cxa_demangle(name, 0, 0, &status);
const string ret = status == 0 ? dem : name;
if (status == 0)
free(dem);
return ret;
}
string getGenericExceptionInfo()
{
const std::type_info* t = __cxxabiv1::__cxa_current_exception_type();
char const* name = t->name();
return deMangle(name);
}
Usage:
catch (...)
{
std::cerr << "caught: " << getGenericExceptionInfo() << std::endl;
}