Having difficulty using a debugger macro - c++

Here is the code:
void DBG() { cerr << "]" << endl; }
template<class H, class... T> void DBG(H h, T... t) {
cerr << to_string(h); if (sizeof...(t)) cerr << ", ";
DBG(t...); }
#ifdef _DEBUG
#define dbg(...) cerr << "LINE(" << __LINE__ << ") -> [" << #__VA_ARGS__ << "]: [", DBG(__VA_ARGS__)
#else
#define dbg(...) 0
#endif
Im currently using g++ on vs code on a mac and whenever I run my program using this and for example
I write dbg(10) on main the program does not even run and does not do anything(it outputs nothing).
How can I change this code so it would work on g++ without having to download clang?
Note: I saw some people use #ifdef LOCAL instead of #ifdef _DEBUG but it still doesn't work for me(does not output anything). How do I get #ifdef LOCAL or #ifdef _DEBUG to work on g++?

Related

C++ try{} throw{} does not work after call to 'C' Function in DLL import?

I am working on program that uses a DLL library (LibPlcTag : https://github.com/libplctag/libplctag) and I wanted to add some exception handling to 'my' code. However after finding this was not working, that is the thrown exceptions were not being caught, I managed to distill it all down to the following bit of demonstration code.
So the question is what is going on here ? Why does a call to a DLL function kill C++ try catch ? Is there a way to fix this ?
FYI : I am using Mingw32 C++ with -std=c++11 compiler build flag on Windows 11.
#include <iostream>
#define SHOWERROR 1
#if SHOWERROR
#ifdef __cplusplus
extern "C" {
#endif
__declspec(dllimport) int plc_tag_check_lib_version(int req_major, int req_minor, int req_patch);
#ifdef __cplusplus
}
#endif
#endif
int main(int argc, char *argv[])
{
#if SHOWERROR
std::cout << "Call DLL function" << std::endl;
plc_tag_check_lib_version(0,0,0);
std::cout << "Call Finished" << std::endl;
#else
std::cout << "No DLL Function Call !!" << std::endl;
#endif
try
{
std::cout << "Throw error" << std::endl;
throw "Error";
}
catch( ... )
{
std::cout << "Exception happened" << std::endl;
}
std::cout << "End" << std::endl;
return 0;
}
With SHOWERROR = 0 the exception is caught :
No DLL Function Call !!
Throw error
Exception happened
End
C:\...\test>
But with SHOWERROR = 1 the exception is not caught and the program terminates without printing 'End' :
Call DLL function
Call Finished
Throw error
C:\...\test>
After working on the hunch that my build LibPlcTag was broken in some way I went back to the beginning and instead of using the MinGW32 (5.1.0) that was installed by PlatformIO for 'platform = windows_x86' I installed MSYS2 and the mingw-w64-i686-toolchain.
I then re-built the LibPlcTag library to get a new DLL.
I then used the mingw toolchain above to rebuild the my test app. Now it works and the exception is caught.
The final test code :
#include <iostream>
#include <fstream>
#define SHOWERROR 1
#if SHOWERROR
#ifdef __cplusplus
extern "C" {
#endif
__declspec(dllimport) int plc_tag_check_lib_version(int req_major, int req_minor, int req_patch);
#ifdef __cplusplus
}
#endif
#endif
// void not_called()
// {
// std::cout << "Call DLL function" << std::endl;
// #if SHOWERROR
// plc_tag_check_lib_version(0,0,0);
// #endif
// std::cout << "Call Finished" << std::endl;
// }
int main(int argc, char *argv[])
{
#if SHOWERROR
std::cout << "Call DLL function" << std::endl;
plc_tag_check_lib_version(0,0,0);
std::cout << "Call Finished" << std::endl;
#else
std::cout << "No DLL Function Call !!" << std::endl;
#endif
try
{
std::cout << "Throw error" << std::endl;
throw "Error";
}
catch( ... )
{
std::ofstream debugFile("debug.txt");
debugFile << "Exception happened" << std::endl;
debugFile.close();
std::cout << "Exception happened" << std::endl;
}
std::cout << "End" << std::endl;
return 0;
}
And output :
Call DLL function
Call Finished
Throw error
Exception happened
End
C:\...\test>
Thank you to those that contributed the above thoughtful comments...

using stream to log information in C++

I have a C++ class which logs messages to a std::ofstream. In the class definition is this code:
#ifdef NDEBUG
#define FOO_LOG(msg) /* calls to log messages are no-op in release mode */
#else
std::ofstream log_stream;
#define FOO_LOG(msg) if (log_stream.is_open()) { log_stream << msg << std::endl; }
#endif
The constructor for that class has several things it checks, and in certain situations will open the log file similar to this:
#ifndef NDEBUG
log_stream.open("output.log");
#endif
Then in the code, it calls the C macro like this:
FOO_LOG("stuff=" << stuff << " in loop counter #" << xyz)
It is convenient that you can pass multiple params to the FOO_LOG() macro. There are obvious limitations, like when logging messages from multiple threads, but this is only used for simple logging in debug builds.
What I want to know is whether there is a different/better way to deal with the msg parameter in C++? Is there a simpler/cleaner way to implement something similar to FOO_LOG() in C++?
Instead of having #ifdef NDEBUG everywhere in your code you can have a #ifdef NDEBUG at the start of the header to define other useful macros.
For me FOO_LOG("stuff=" << stuff << " in loop counter #" << xyz); feels a bit unnatural. I would have to keep reffering back to the macro definition to see how it's implemented. Instead you can define a macro to behave as an std::ostream and use it as you would any other stream. That way you can do stuff like LOG_STREAM << "stuff=" << stuff << " in loop counter #" << xyz << std::endl;.
For this answer I had some inspiration from this question.
#include <fstream>
#define NDEBUG
//An ostream class that does nothing
class DummyStream : public std::ostream {
public:
int overflow(int c) { return c; }
} dummyStream;
//Here we let NDEBUG define other macros.
#ifdef NDEBUG
std::ofstream logStream;
std::ostream& oLogStream(*(std::ostream*)&logStream);
#define LOG_STREAM (logStream.is_open() ? oLogStream : dummyStream)
#define OPEN_LOG(log) (logStream.is_open() ? logStream.close(), logStream.open(log, std::ofstream::out | std::ofstream::app) : \
logStream.open(log, std::ofstream::out | std::ofstream::app))
#define CLOSE_LOG() (logStream.close())
#else
#define LOG_STREAM (dummyStream)
#define OPEN_LOG(log) //no-op
#define CLOSE_LOG() //no-op
#endif // NDEBUG
int main(int argc, char* argv[]) {
//will only log if NDEBUG is defined.
OPEN_LOG("log.txt");
std::string stuff("stuff to log");
for(int xyz = 0; xyz < 4; xyz++) {
LOG_STREAM << "stuff=" << stuff << " in loop counter #" << xyz << std::endl;
}
CLOSE_LOG();
//Log is not open so it will not log anything.
stuff = "stuff to not log";
for(int xyz = 0; xyz < 4; xyz++) {
LOG_STREAM << "stuff=" << stuff << " in loop counter #" << xyz << std::endl;
}
return 0;
}
Benifits of this?
LOG_STREAM is treated more intuitively like any other stream.
OPEN_LOG(log) will close already open logs before opening a new one and when NDEBUG is not define it will do nothing.
CLOSE_LOG() will close a log and when NDEBUG is not define it will do nothing.
Don't need to type #ifdef NDEBUG ... #endif everywhere.
dummyStream can be replaced with something like std::cout or some other stream.
Down side?
You have this DummyStream that's just in your code and a few no-op's are performed when LOG_STREAM is used when NDEBUG is not defined.

Visual Studio C++ code how to autoindent preprocessor directives

How to use autoindent the preprocessor directives
For example in Visual studio all preprocessor directives intended like
this
void test(){
#if _SOME_VAR
std::cout << "test" << std::endl;
#if _SOME_VAR2
std::cout << "test2" << std::endl;
#endif
#endif
}
How can i make code auto indents like this
void test(){
#if _SOME_VAR
std::cout << "test" << std::endl;
#if _SOME_VAR2
std::cout << "test2" << std::endl;
#endif
#endif
}
The solution is
Tools->Options->Text Editor->Indentation->Position of preprocessor
directives

Exception messages hidden by visual studio/debugger breaking on the wrong line

Visual studio is hiding my exception messages. Take the following code example:
#include <stdio.h>
#include <iostream>
#include <exception>
void exceptional_method(){
throw std::runtime_error("Hello from exceptional_method!");
}
int main(){
std::cout << "Hello world!" << std::endl;
exceptional_method();
std::cin.get();
}
Visual studio gives me some vague addresses:
Unhandled exception at 0x76A9DDC2 in ExceptionTest.exe: Microsoft C++ exception: std::runtime_error at memory location 0x006FFD34.
Whereas linux mint gives me the following output on the terminal:
Hello world!
terminate called after throwing an instance of 'std::runtime_error'
what(): Hello from exceptional_method!
Aborted (core dumped)
I've googled a bunch, messed around with the settings in Visual studio, but cannot figure this out. My current workaround is writing the exception message to console before throwing so that I can at least catch the message so I know which exception was thrown.
inline void throw_exception(string& message)
{
cout << message << endl;
throw runtime_error(message);
}
This is not ideal. Any help would be greatly appreciated.
edit:
Getting the debugger to break on the actual exception instead of a few lines ahead was the problem, causing me to investigate the wrong code.
The following solution is what I was looking for.
#ifndef DEBUG_ASSERT_H
#define DEBUG_ASSERT_H
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::string;
inline void log_failed_assert(const string message, const string expression, const string file, const long line) {
cout << "Assert failed." << endl;
cout << "Expression: " << expression << endl;
cout << "Message : " << message << endl;
cout << "File : " << file << endl;
cout << "Line : " << line << endl;
}
inline void windows_break()
{
#ifdef _WIN32
__debugbreak();
#endif
}
//do {
//} while (0)
#ifdef _DEBUG
#ifdef _WIN32
#define DEBUG_ASSERT(expr, s) do{\
if(!(expr)){\
log_failed_assert(s, #expr, __FILE__, __LINE__);\
__debugbreak();\
}\
} while(0)
#else
#define DEBUG_ASSERT(expr, s) do{\
if(!(expr)){\
log_failed_assert(s, #expr, __FILE__, __LINE__);\
}\
} while(0)
#endif
#else
#define DEBUG_ASSERT(expr, s)
#endif
#endif
Exceptions are there to be catched. If you dont catch it your program will terminate. If this is what you want, there are easier ways to terminate. If you catch the exception in main you can use the message to eg print it:
#include <exception>
#include <iostream>
void exceptional_method(){
throw std::runtime_error("Hello from exceptional_method!");
}
int main(){
std::cout << "Hello world!" << std::endl;
try {
exceptional_method();
} catch (std::exception& e) {
std::cout << e.what();
}
std::cin.get();
}
As RichardCritten pointed out, it is mint being nice to you rather than visual studio "hiding" the message, as there is no requirement to print the message when your program terminates.

How to process C++ file to remove ifdef'd out code

I have inherited a piece of C++ code which has many #ifdef branches to adjust the behaviour depending on the platform (#ifdef __WIN32, #ifdef __APPLE__, etc.). The code is unreadable in its current form because these preprocessor directives are nested, occur in the middle of functions and even in the middle of multi-line statements.
I'm looking for a way of somehow specifying some preprocessor tags and getting out a copy of the code as if the code had been pre-processed with those flags. I'd like the #include directives to be left untouched, though.
Example:
#include <iostream>
#ifdef __APPLE__
std::cout << "This is Apple!" << std::endl;
#elif __WIN32
std::cout << "This is Windows" << std::endl;
#endif
would turn into:
#include <iostream>
std::cout << "This is Apple!" << std::endl;
after being processed by: tool_i_want example.cpp __APPLE__.
I've hacked a quick script that does something similar, but I'd like to know of better tested and more thorough tools. I am running a Linux distribution.
I have decided against just running the C-preprocessor because if I'm not mistaken it will expand the header files, which would make everything more unreadable.
Use unifdef. It is designed for that purpose.
Complementing Basile Starynkevitch's answer, I want to mention coan. The major advantage is that, when used with -m it does not require the user to unset all symbols they want undefined.
This code:
#include <iostream>
#ifdef __ANDROID__
std::cout << "In Android" << std::endl;
#endif
#ifndef __WIN32
std::cout << "Not a Windows platform" << std::endl;
#endif
#ifdef __APPLE__
std::cout << "In an Apple platform" << std::endl;
#elif __linux__
std::cout << "In a Linux platform" << std::endl;
#endif
would result in this code if simply run as: unifdef -D__APPLE__ example.cpp:
#include <iostream>
#ifdef __ANDROID__
std::cout << "In Android" << std::endl;
#endif
#ifndef __WIN32
std::cout << "Not a Windows platform" << std::endl;
#endif
std::cout << "In an Apple platform" << std::endl;
Using unifdef one would need to use
unifdef -D__APPLE__ -U__ANDROID__ -U__WIN32 -U__linux__ example.cpp:
#include <iostream>
std::cout << "Not a Windows platform" << std::endl;
std::cout << "In an Apple platform" << std::endl;
This can get exhausting quickly when dealing with code considering several different platforms. With coan it's a matter of:
coan source -D__APPLE__ -m example.cpp.