Using lambdas in c++11 visualstudio11 with winapi [duplicate] - winapi

This question already has answers here:
Use CreateThread with a lambda
(3 answers)
how to specify vc11 lambda calling convention
(1 answer)
Closed 9 years ago.
Instead of
CreateThread(NULL, NULL, function, NULL, NULL, NULL);
I was interested in trying
CreateThread(NULL, NULL, [](LPTHREAD_START_ROUTINE){ int x = 0; return x;}, NULL, NULL, NULL);
I get ERROR: No suitable conversion function from lambda []int (LPTHREAD_START_ROUTINE)->int to LPTHREAD_START_ROUTINE exists.

The signature on your lambda function is incorrect. It needs to accept void* and return DWORD. Try the following
LPTHREAD_START_ROUTINE pStart = [](void* pValue) -> DWORD { int x = 0; return x; };
::CreateThread(NULL, NULL, pStart, NULL, NULL, NULL);
Note: I believe this will only work on Visual Studio 2012 and higher. I do not believe lambda to function pointer conversions were implemented before then

Related

What does '->' mean after a function declaration in C++ 11? [duplicate]

This question already has answers here:
Arrow operator (->) in function heading
(3 answers)
Closed 4 years ago.
What is the syntax used here with '-> decltype' after the operator() signature and what is it for?
template<>
struct less<void>
{ // transparent functor for operator<
typedef int is_transparent;
template<class _Ty1,
class _Ty2>
constexpr auto operator()(_Ty1&& _Left, _Ty2&& _Right) const
-> decltype(static_cast<_Ty1&&>(_Left)
< static_cast<_Ty2&&>(_Right))
{ // transparently apply operator< to operands
return (static_cast<_Ty1&&>(_Left)
< static_cast<_Ty2&&>(_Right));
}
};
this is the code from C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.15.26726\include\xstddef line 276.
Why are the following two lines duplicated?
(static_cast<_Ty1&&>(_Left)
< static_cast<_Ty2&&>(_Right))
->decltype(static_cast<_Ty1&&>(_Left) returns the type of static_cast<_Ty1&&>(_Left) and declare it as the return type of the function.
E.G.
auto function(int x ) -> int and int function(int x ) are the same

How to start thread using object member function of non-copyable non-movable class? [duplicate]

This question already has answers here:
c++11 std::mutex compiler error in Visual Studio 2012
(3 answers)
Closed 4 years ago.
Why does below code does not compile in Visual Studio 2015.
The same code works properly if ran on ideone.
class FooMutex
{
std::mutex stm;
public:
void foo() {}
};
int main()
{
FooMutex o;
std::thread t1(&FooMutex::foo, o);
}
Error is: C2664 'std::tuple<void (__thiscall FooMutex::* )(void),FooMutex>::
tuple(std::tuple<void (__thiscall FooMutex::* )(void),FooMutex> &&)'
: cannot convert argument 1 from 'void (__thiscall FooMutex::* )(void)' to 'std::allocator_arg_t'
There are multiple ways to do what you want:
Pass pointer instead: std::thread t1(&FooMutex::foo, &o);
Use std::bind: std::thread t1(std::bind(&FooMutex::foo, &o));
Use std::bind: std::thread t1(&FooMutex::foo, std::ref(o));
Use lambda function: std::thread t1([&o]() { o.foo(); });
The 3rd and 2nd ways are essentially the same as the 1st one. The 4th actually has the chance of being the most efficient one, since lambda will have smaller size than callable object that contains both pointer and member function pointer and thus has higher chance of being embedded into the internal std::function object, instead of being allocated on heap. Not that it changes anything, but still.

Storing the global js object in JS::Heap<T> provokes crash in JS_DestroyRuntime if still in scope

After learning from this question,
I'm trying to store SpiderMonkey's global object on the heap. This seems to work as long as it goes out of scope before JS_DestroyRuntime is called. In my code however, the global object is a class member and thus cannot go out of scope before the runtime is destroyed in the class's destructor.
Unfortunately, this leads to the Monkey crashing in JS::~Heap with the following stack trace:
1 js::gc::Cell::storeBuffer() const Heap.h 1339 0x10004f905
2 JSObject::writeBarrierPost(void *, JSObject *, JSObject *) jsobj.h 655 0x1000a6fc8
3 js::InternalGCMethods<JSObject *>::postBarrier(JSObject * *, JSObject *, JSObject *) Barrier.h 254 0x1000a6df0
4 JS::HeapObjectPostBarrier(JSObject * *, JSObject *, JSObject *) Barrier.cpp 173 0x100bc1636
5 js::GCMethods<JSObject *>::postBarrier(JSObject * *, JSObject *, JSObject *) RootingAPI.h 551 0x100003065
6 JS::Heap<JSObject *>::post(JSObject * const&, JSObject * const&) RootingAPI.h 271 0x10000302b
7 JS::Heap<JSObject *>::~Heap() RootingAPI.h 237 0x10000369e
8 JS::Heap<JSObject *>::~Heap() RootingAPI.h 236 0x100002f75
9 MyMonkeyClass::~MyMonkeyClass() main.cpp 64 0x100003725
10 MyMonkeyClass::~MyMonkeyClass() main.cpp 58 0x100002aa5
11 main main.cpp 110 0x100002a12
12 start 0x1000029d4
Here is a minimal example triggering the problem. I've left the GC tracing calls out intentionally, they don't change the outcome.
#include <js/Initialization.h>
#include <jsapi.h>
#include <QDebug>
// The class of the global object. Just a dummy.
static JSClass global_class = {
"global",
JSCLASS_GLOBAL_FLAGS,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
JS_GlobalObjectTraceHook
};
class MyMonkeyClass
{
public:
MyMonkeyClass() {
Q_ASSERT( JS_Init() );
auto runtime = JS_NewRuntime( 5 * 1024 * 1024 /*heap space*/ );
Q_ASSERT( runtime );
m_context = JS_NewContext( runtime, 8192 /*default. keep.*/ );
Q_ASSERT( m_context );
JSAutoRequest ar( m_context );
// Not sure which of these alternatives is the correct way with JS::Heap
m_global = JS::RootedObject( m_context,
JS_NewGlobalObject( m_context, &global_class, nullptr, JS::FireOnNewGlobalHook ) );
//global = JS_NewGlobalObject( context, &global_class, nullptr, JS::FireOnNewGlobalHook );
Q_ASSERT( m_global.get() );
}
~MyMonkeyClass() {
auto runtime = JS_GetRuntime( m_context );
JS_DestroyContext( m_context );
JS_DestroyRuntime( runtime );
JS_ShutDown();
}
private:
JSContext *m_context;
JS::Heap<JSObject*> m_global;
};
int main( int, char** )
{
MyMonkeyClass mmc;
return 0;
}
While composing this question I found out that setting m_global = nullptr; in the dtor before destroying things actually avoids the crash. Now my final question is:
Is this the correct fix? If yes, why? Does SM maybe assume that a non-null JS::Heap pointer refers to still-in-use memory and thus it panics?
Your initial problem is caused by a wrong order of object deallocations.
A C++ class is destructed in a construction reverse order that is, a call to a class destructor is followed by the class member destructors. Members are destroyed in their declaration reverse order. That means that in your case:
~MyMonkeyClass() is entered
JS_Destroy* and JS_ShutDown is called
JS::~Heap is called. However, JS engine is already gone and that causes undefined behaviour - crash in your case.
By setting m_global to nullptr you prevent JS::~Heap() from going down to JS API to clean up memory. That dodges the crash but leaves you with a possibility of a memory leak.
A proper fix is cleaning everything up in a correct order.
One way would be defining a yet another class "JsUpDown" that initialises JS engine, creates JS runtime and JS context in constructor and calls JS_Destroy* and JS_ShutDown in destructor. Then MyMonkeyClass would look like:
class MyMonkeyClass
{
MyMonkeyClass() : m_engine(), m_global() // just to make it explicit
{
JSAutoRequest ar(m_engine.m_context);
m_global = JS::RootedObject(...);
}
~MyMonkeyClass() {} // no need for the destructor now
JsUpDown m_engine; // Should be first. The order is important:
// Members are destroyed in reverse order.
JS::Heap<JSObject*> m_global;
};

Linux and KERN_PROC

I'm attempting to get the information of another process via the sysctl interface
int mib[4] = {0};
size_t len = sizeof( mib ) / sizeof( int );
struct kinfo_proc kp;
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PID;
mib[3] = 3027;
sysctl(mib, 4, &kp, &len, NULL, 0);
Error:
test.cpp: In function ‘int main(int, char**)’:
test.cpp:13:22: error: aggregate ‘main(int, char**)::kinfo_proc kp’ has incomplete type and cannot be defined
test.cpp:16:13: error: ‘KERN_PROC’ was not declared in this scope
Had a good look but to no definitive answer. Does linux support KERN_PROC via the sysctl system call.
Distro: Centos 6.2
It looks like you're trying to use a BSD/OS X specific kernel interface.
For obvious reasons that won't work on Linux.
Take a look at include/linux/sysctl.h to find out what is supported.

C++ - Window Message loop is freezing

I have this class here that I made based on another one I had. It is supposed to handle the whole creating windows and stuff, but it seems to be getting into a hang now. The older version used to work fine, I don't know WHAT I may have forgotten to add to this one that might be causing it to hang like this.
This is the message loop:
int Window::HandleMessages()
{
while(GetMessage(&this->windat.msgs, NULL, 0, 0))
{
TranslateMessage(&this->windat.msgs);
DispatchMessage(&this->windat.msgs);
}
return this->windat.msgs.wParam;
}
Pretty basic stuff, I don't know why, but it will simply hang... When I run the program, it'll just show me an empty prompt window, and by testing, I got it to show a message box if I used it before the while loop, but inside it doesn't work. I've been trying to compare both this class and the older one and haven't figured out what might be wrong with this. Could anyone tell me what could possibly trigger this behaviour?
Thanks
OK, now this left me pretty confused. By messing around with GetLastError, it seems that it is returning error 2 (file not found) ANYWHERE I put it, even if right at the start of the Main, before I instantiate my Window class. If I call GetLastError anytime after CreateWindowEx, it'll return an error like 1047 or something, about class not found or something. HWND becomes NULL too
Here is the code for the main.cpp:
#include "SimpWin/SimpWin.h"
#include <stdio.h>
// Make the class name into a global variable
char szClassName[] = "WindowsApp";
void ErrorExit(LPTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
// Display the error message and exit the process
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
sprintf((char*)lpDisplayBuf,
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
ExitProcess(dw);
}
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nFunsterStil)
{
ErrorExit(TEXT("CreateWindowEx"));
Window* win = Window::CreateWindowClass(hThisInstance, szClassName, WindowProcedure);
if(!win->Register())
{
return 0;
}
win->Show(nFunsterStil);
int res = win->HandleMessages();
delete win;
return res;
}
/* This function is called by the Windows function DispatchMessage() */
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
return DefWindowProc (hwnd, message, wParam, lParam);
}
This here, is the code for the Window::Register function:
int Window::Register()
{
if(this->windat.wincl.hIcon == NULL)
{
this->windat.wincl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
}
if(this->windat.wincl.hIconSm == NULL)
{
this->windat.wincl.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
}
if(!RegisterClassEx(&this->windat.wincl))
{
return 0;
}
this->windat.hwnd = CreateWindowEx (
0, /* Extended possibilites for variation */
(char*) this->windat.sName, /* Classname */
(char*) this->windat.sTitle, /* Title Text */
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, /* default window */
CW_USEDEFAULT, /* Windows decides the position */
CW_USEDEFAULT, /* where the window ends up on the screen */
this->windat.cDimension.width, /* The programs width */
this->windat.cDimension.height, /* and height in pixels */
HWND_DESKTOP, /* The window is a child-window to desktop */
NULL, /* No menu */
this->windat.hInstance, /* Program Instance handler */
NULL /* No Window Creation data */
);
return 1;
}
I'm lost here, I don't know why the eff this is going on... :/
Use PeekMessage instead of GetMessage.
Check the return value to GetMessage() - your while loop won't exit if there are errors. It should look like this:
while (GetMessage(&this->windat.msgs, NULL, 0, 0) > 0)
{
...
}
Well, I finally got it working! :D
It actually had to do with a completely unrelated class I had here. It is a String class (which descended from Array) which I made, and the copy function had a bug, it would copy the character array I passed to it, but would not update the length field of the class...
That copy function would be called whenever I had to set the class to a value through operator=. The length is required for the operator char* to convert the class to c-format string. I'd use that cast when passing the ClassName and Title values to CreateWindowEx, and it would return me an array of 0 chars, and that's where hell happened.
Now I fixed that lib up, and it's working fine now. Thanks :D
Even though it's pretty old... from MSDN on GetMessage:
Unlike GetMessage, the PeekMessage function does not wait for a message to be posted before returning.
That is, GetMessage waits for next message to become available. You treat this wait in progress as a freeze, supposedly because you did not actually have the intention to wait for messages.
Note that you can attach debugger at the time of supposed freeze, pause the execution and inspect the call stacks of the threads. Once you find your thread and its call stack and its GetMessage in progress on the stack - you isolate the problem well enough to know where to read on documented behavior.

Resources