At the current moment I am trying to test IAutoComplete COM interface, which requires me to make use of MSVC cpp compiler. I am faced with a problem I never faced in MingGW. MSVC sees my throw statement and completely ignores it. So I don't know if there is a setting I didn't set.
Alright I got a down vote which I probably deserve for giving a bad example. I thought that it failed to throw because it was in a struct but tries with a fresh struct proved me wrong. I might not be able to offer a reproducible example but I will try.
Prepare for alot of code.
Jav/AutoObject.h
#ifndef JAV_WIN32_AUTO_OBJECT_HPP
#define JAV_WIN32_AUTO_OBJECT_HPP
#include <Jav/config.h>
namespace Jav
{
struct AutoObject
{
virtual ~AutoObject(){}
void* operator new(size_t sz);
};
AutoObject* shallowCopy(AutoObject*);
AutoObject* deleteObject(AutoObject*);
}
#endif // JAV_WIN32_AUTO_OBJECT_HPP
Jav/win32/widgets/widgets_ex.h
#ifndef JAV_WIN32_GUI_WIDGETS_EX_HPP
#define JAV_WIN32_GUI_WIDGETS_EX_HPP
#include <Jav/win32/widgets/widgets.h>
namespace Jav { namespace win32 {
class Widget
{
public:
Widget(HWND widget=nullptr) : widget(widget){}
operator HWND() { return widget; }
public:
void setId(int id) { SetWindowLong(widget,GWLP_ID,id); }
void destroy() { DestroyWindow(widget); widget = NULL; }
void show() { ShowWindow(widget,SW_SHOW); }
void hide() { ShowWindow(widget,SW_HIDE); }
protected:
HWND widget;
};
}}
#endif // JAV_WIN32_GUI_WIDGETS_EX_HPP
Jav/win32/window/Window.h
#include <Jav/win32/widgets/widgets_ex.h>
using Window = Widget;
Jav/win32/window/SimpleWindow.h
#ifndef JAV_WIN32_WINDOW_SIMPLE_WINDOW_HPP
#define JAV_WIN32_WINDOW_SIMPLE_WINDOW_HPP
#include <Jav/AutoObject.h>
#include <Jav/win32/window/Window.h>
namespace Jav { namespace win32 {
struct Content__ : AutoObject
{
virtual void onCreate(HWND,CREATESTRUCTA*) {}
virtual void onDestroy() {}
virtual void onSize(int w,int h) {}
virtual void onDraw(Canvas&) {}
};
class SimpleWindow : public Window
{
public:
SimpleWindow(Content__*, const char *title, size_t w,size_t h,
int style=WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,
int ex_style=0);
public:
bool isOpen();
void close();
const MSG& getMessage();
const MSG& peekMessage();
void dispatchMessage(const MSG&);
private:
static ATOM registerWindow();
static LRESULT CALLBACK windowProc(HWND,UINT,WPARAM,LPARAM);
static HWND createWindow(Content__*, const char *,HMENU, size_t,size_t, int,int);
private:
MSG msg;
};
}}
#endif // JAV_WIN32_WINDOW_SIMPLE_WINDOW_HPP
AutoObject.cpp
#include <Jav/AutoObject.h>
#include <unordered_map>
#include <objbase.h>
namespace {
struct AutoObjectsMap : std::unordered_map<Jav::AutoObject*,size_t>
{
~AutoObjectsMap() { for(auto &obj : *this) CoTaskMemFree(obj.first); }
};
AutoObjectsMap *alloc_objects_ptr;
struct AutoObjectsMapMgr
{
~AutoObjectsMapMgr() { delete alloc_objects_ptr; };
};
}
#define alloc_objects (*alloc_objects_ptr)
namespace Jav
{
void* AutoObject::operator new(size_t sz)
{
auto mem = CoTaskMemAlloc(sz);
if(!alloc_objects_ptr) alloc_objects_ptr = new AutoObjectsMap();
alloc_objects[(AutoObject*)mem] = 1;
return mem;
}
AutoObject* shallowCopy(AutoObject *r)
{
auto elem = alloc_objects.find(r);
if( elem != alloc_objects.end() ) alloc_objects[r];
return r;
}
AutoObject* deleteObject(AutoObject *mem)
{
auto elem = alloc_objects.find(mem);
if( elem != alloc_objects.end() )
{
if(--elem->second == 0)
{
mem->~AutoObject();
CoTaskMemFree(mem);
alloc_objects.erase(elem);
return nullptr;
}
}
return mem;
}
}
SimpleWindow.cpp
#include <Jav/win32/window/SimpleWindow.h>
namespace Jav { namespace win32 {
namespace {
LRESULT CALLBACK SimpleWindow::windowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
Content__ *obj = (Content__*)GetWindowLongPtrA(hwnd,GWLP_USERDATA);
auto getWidth = [lParam](){ return LOWORD(lParam); };
auto getHeight = [lParam](){ return HIWORD(lParam); };
auto getX = [lParam](){ return LOWORD(lParam); };
auto getY = [lParam](){ return HIWORD(lParam); };
auto getWidget = [lParam](){ return (HWND)lParam; };
auto widgetId = [wParam](){ return LOWORD(wParam); };
auto widgetEvent = [wParam](){ return HIWORD(wParam); };
auto menuType = [wParam](){ return LOWORD(wParam); };
auto eventId = [wParam](){ return LOWORD(wParam); };
switch (uMsg)
{
case WM_CREATE:
{
CREATESTRUCT *cs = ((CREATESTRUCTA*)lParam);
obj = (Content__*)cs->lpCreateParams;
SetWindowLongPtr(hwnd,GWLP_USERDATA,(LONG_PTR)obj);
obj->onCreate(hwnd,cs);
return 0;
}
case WM_DESTROY:
obj->onDestroy();
deleteObject(obj);
return 0;
case WM_SIZE:
obj->onSize(getWidth(),getHeight());
return 0;
default: return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
ATOM SimpleWindow::registerWindow()
{
WNDCLASSEX wincl = {};
wincl.cbSize = sizeof(WNDCLASSEX);
wincl.lpszClassName = "JavWin32WindowSimpleWindow";
wincl.lpfnWndProc = SimpleWindow::windowProc;
wincl.style = CS_HREDRAW|CS_VREDRAW;
wincl.hIcon = LoadIcon(NULL,IDI_APPLICATION);;
wincl.hIconSm = LoadIcon(NULL,IDI_APPLICATION);
wincl.hCursor = LoadCursor(NULL,IDC_ARROW);
wincl.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
wincl.cbWndExtra = WINDOW_WND_EXTRA_BYTES;
return RegisterClassEx(&wincl);
}
SimpleWindow::SimpleWindow(Content__ *obj,const char *title, size_t w,size_t h, int style,int ex_style)
: Window( createWindow(obj,title,NULL, w,h, style,ex_style) ),
app_ctx(*this)
{
msg.message = 0;
show();
}
bool SimpleWindow::isOpen()
{
return msg.message != WM_QUIT;
}
void SimpleWindow::close()
{
DestroyWindow(*this);
}
const MSG& SimpleWindow::getMessage()
{
GetMessageA(&msg,*this,0,0);
return msg;
}
const MSG& SimpleWindow::peekMessage()
{
PeekMessageA(&msg,*this,0,0,PM_REMOVE);
return msg;
}
void SimpleWindow::dispatchMessage(const MSG &msg)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}}
main.cpp
#include <Jav/AutoObject.h>
#include <Jav/win32/window/SimpleWindow.h>
using namespace Jav::win32;
class Content : public Content__
{
IAutoComplete *pac = NULL;
IAutoComplete2 *pac2 = NULL;
//IUnknown *punkSource;
//ColumnList columnList;
public:
~Content()
{
if(pac) pac->Release();
if(pac2) pac2->Release();
}
void onCreate(HWND hwnd,CREATESTRUCTA*)override
{
throw; //doesn't throw or terminate
HWND textBox; // pretend this is an edit control
attachAutoCompleteObject(textBox); //doesn't throw either
}
void attachAutoCompleteObject(HWND hwnd)
{
HRESULT hr = CoCreateInstance(CLSID_AutoComplete, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pac));
if(FAILED(hr)) throw "Failed to create AutoComplete Object\n";
hr = pac->Init(hwnd, &columnList, NULL, NULL);
if(FAILED(hr)) throw "Failed to attach auto complete object\n";
hr = pac->QueryInterface(IID_PPV_ARGS(&pac2)); rep(pac2);
if (FAILED(hr)) throw "Failed to set autocomplete options\n";
hr = pac2->SetOptions(ACO_AUTOSUGGEST);
}
};
int main()
{
Content content;
SimpleWindow win(&content,"",640,480);
while(win.isOpen())
{
auto &msg = win.getMessage();
win.dispatchMessage(msg);
}
}
CodePudding user response:
throw;
alone is not doing what you think it does. Actually it is unclear what you expected to happen. From cppreference:
throw expression (1)
throw (2)
- [...]
- Rethrows the currently handled exception. Abandons the execution of the current catch block and passes control to the next matching exception handler (but not to another catch clause after the same try block: its compound-statement is considered to have been 'exited'), reusing the existing exception object: no new objects are made. This form is only allowed when an exception is presently being handled (it calls std::terminate if used otherwise). The catch clause associated with a function-try-block must exit via rethrowing if used on a constructor.
When no expection is currently being handled, then throw;
alone is wrong. It outright terminates the program. If you want to throw an exception, try for example this
throw 42;
throw; //This also throws;
No, this should not throw. It should call std::terminate
.
CodePudding user response:
So you appear to have throw "literal"
instead of just throw;
you originally posted. Then it indeed should throw. The problem here is that you attempt to throw exception that goes through Windows DLLs, like GetMessage
/DispatchMessage
fuctions or COM method dispatch, which is not guarrantied to work.