Is it okay to do "#ifdef DEBUG( ... ) __VA_ARGS__"? - c++

Global.h
#ifndef GLOBAL_H
# define GLOBAL_H
#define DEBUG
#ifdef DEBUG
# define IF_DEBUG( ... ) __VA_ARGS__
#else
# define IF_DEBUG( ... )
#endif /* DEBUG */
#endif /* GLOBAL_H */
Main.cpp
#include <string>
#include <iostream>
#include "Global.h"
int main() {
int A = 1;
int B = 2;
int C = 0;
IF_DEBUG(
std::cout << "\nStep 1> Calculating...\n";
)
C = A + B;
// DO WHATEVER
IF_DEBUG(
std::cout << "\nStep n> ...\n";
)
// ...
std::cout << C << std::endl;
// Note: I could also do some operations within the IF_DEBUG macro.
IF_DEBUG(
int X = 10;
int Y = 5;
int Z = X / Y;
std::cout << Z << std::endl;
)
IF_DEBUG(
std::cout << "\nDebugged! This program has been paused. Enter any key to continue!\n";
::getchar();
)
return 0;
}
Do you see how I defined IF_DEBUG in the Global header file (Global.h) and how I constantly used
it in the Main source file (Main.cpp) for debugging purposes?
Is it okay and safe to do that?
I am asking this question because I am unsure if its okay to do that. When I show this to my friend and he said its "bad" to do that. Therefore, I am unsure.

This is a very common and useful trick. But it's better not to have the #define DEBUG in the source code. You can define it in the compile command line instead. g++ -DDEBUG -c file.cpp will compile the code as if DEBUG was defined.
If you're using a Makefile you can add it to the CPPFLAGS (C Preprocessor Flags) variable: CPPFLAGS=-DDEBUG.
If you're using an IDE try to find the C Preprocessor Flags in the project settings.

Related

Class is not defined in implementation file

When I try to compile my implementation file using g++ -c Sorting_Functions.cpp, I get this message
error: use of undeclared identifier 'IntSort'
IntSort.h
#ifndef INTSORT_H_
#define INTSORT_H_
#include "Sorting_Functions.cpp"
class IntSort
{
public:
IntSort();
void print();
private:
int arr[5];
int len;
};
#endif
Sorting_Functions.cpp
#include "IntSort.h"
using namespace std;
IntSort::IntSort()
{
arr[0] = 7;
arr[1] = 3;
arr[2] = 2;
arr[3] = 6;
arr[4] = 4;
len = 5;
}
// prints the lists to the user
void IntSort::print()
{
cout << "{ ";
for (int i = 0; i < len; i++) {
cout << arr[i] << " ";
}
cout << "}";
}
The problem is the inclusion of a source file (.cpp or .cc). Only header files (.h) should be included, and all source files should be compiled. Remove the source file #include and the code should be fine.
The "undeclared identifier" error is caused by Sorting_Functions.cpp including IntSort.h which in turn includes Sorting_Functions.cpp - the compiler will first see the type IntSort being used, which at this point has not yet been declared (which happens in IntSort.h after the #include).

Working Templates header file, not working anymore

So, I had 2 files:
DFH_lib.h
Lib_Test.cpp
The programs were working perfectly just some 20-24 hours ago(I even have the executable file), I decided exclude the DFH_lib.cpp file as it is effectively empty (see below) and voila! It's giving me
Declaration Syntax Error
on the first line of the top template function.
I tried rearranging but it didn't help
This is super annoying, I'm stuck with Turbo because of my school and now this template based header file that I spend weeks building is suddenly not compiling.
Code
This is how the DFH_lib.h file starts (excluding the multi-line comment):
#ifndef DFH_lib_H
#define DFH_lib_H
enum bool { false, true };
template <class T> //Error on this line
void AddColumn(T data, const int& width) {
cout<<setw(width)<<data<<" | ";
}
NOTE: The error comes while compiling the DFH_lib.h
Question
On adding a DFH_lib.cpp file to the project, with nothing but this:
#ifndef _DFH_lib_CPP
#define _DFH_lib_CPP
#include"DFH_lib.h"
#if !defined __FSTREAM_H
#include<fstream.h>
#endif
#if !defined __IOMANIP_H
#include<iomanip.h>
#endif
#if !defined __CONIO_H
#include<conio.h>
#endif
#if !defined __STDIO_H
#include<stdio.h>
#endif
#if !defined __STRING_H
#include<string.h>
#endif
#endif
Everything worked fine! Why is this happening? All the headers written in DFH_lib.cpp are already included in the lib_Test.cpp prior to including DFH_lib.h.
In my opinion, the DFH_lib.cpp file is does nothing but it seems to be important none the less.
P.S. - I apologize if this is a duplicate, I know this question exists but I couldn't relate it to my situation. Here, the .cpp is effectively empty but still required.
A quick MCVE, that I put together:
UTILIZATION FILE:
#include<iostream.h>
#include<conio.h>
#include<iomanip.h>
#include"fileio.h"
void fillSpace(char ch, const int& width) {
cout<<setw(width)<<setfill(ch)<<"|";
}
int record_id = 1;
char char_member = 'A';
int int_member = 12;
float float_member = 2.3;
void show_tablular() {
cout<<endl; AddColumn(record_id,7); AddColumn(char_member, 20); AddColumn(int_member, 11); AddColumn(float_member, 13);
}
void main()
{
clrscr();
cout<<endl; AddColumn("Record", 7); AddColumn("Char Member", 20); AddColumn("Int Member", 11); AddColumn("Float Member", 13);
cout<<endl; AddColumn(" ", 7); AddColumn(" ", 20); AddColumn(" ", 11); AddColumn(" ", 13);
show_tablular();
cout<<endl; fillSpace('_', 7+2); fillSpace('_', 20+3); fillSpace('_', 11+3); fillSpace('_', 13+3);
cout<<setfill(' '); //Normalize cout based outputting format
getch();
}
IMPLEMENTATION FILE:
#include"fileio.h"
#if !defined __FSTREAM_H
#include<fstream.h>
#endif
#if !defined __IOMANIP_H
#include<iomanip.h>
#endif
#if !defined __CONIO_H
#include<conio.h>
#endif
#if !defined __STDIO_H
#include<stdio.h>
#endif
#if !defined __STRING_H
#include<string.h>
#endif
HEADER FILE:
#ifndef file_H
#define file_H
enum bool { false, true };
template <class T>
void AddColumn(T data, const int& width) {
cout<<setw(width)<<data<<" | ";
}
#endif
NOTE: They only work if added into a project in the same order from top to bottom otherwise the above error is encountered.

gdb doesn't stop in a line with #include directive

The problem is that, when I set a breakpoint at the line of the #include, gdb just ignore the line and stop at the next instruction in the main (I compiled the main.cpp with g++ -g -O2 -std=c++11).
The program works perfect (-O2 doesn't affect the result at all), but I want to check what exactly does something inside that file, but I can't because gdb doesn't let me enter the code inside the file.
How can I debug code inside other file? Is it even possible?
Edit: Here is the code
main.cpp
#include <iostream>
#include <cstdlib>
#include <chrono>
#include "inc/includes.h"
template <class T>
void PrintVector(T* vector, int size){
for (int i=0; i<size; ++i){
std::cout << vector[i] << " ";
}
std::cout << std::endl;
}
template <class T>
void CheckTime(void (*f)(T*&, int), T* &vector, int size){
std::chrono::high_resolution_clock::time_point tantes, tdespues;
std::chrono::duration<double> transcurrido;
tantes = std::chrono::high_resolution_clock::now();
(*f)(vector, size);
tdespues = std::chrono::high_resolution_clock::now();
transcurrido = std::chrono::duration_cast<std::chrono::duration<double>(tdespues - tantes);
std::cout << size << " " << transcurrido.count() << std::endl;
}
int main(int argc, char * argv[]){
if (argc != 2){
std::cerr << "Formato " << argv[0] << " <num_elem>" << std::endl;
return -1;
}
int n = atoi(argv[1]);
int range;
#if defined RADIXSORTLSD || defined RADIXSORTMSD
unsigned short * array = new unsigned short[n];
range = (n<65536)?n:65536;
#else
unsigned int * array = new unsigned int[n];
range = n;
#endif
srand(time(0));
for (int i = 0; i < n; i++){
array[i] = rand()%range;
}
#ifdef PRINT
PrintVector(array, n);
#endif
#include "inc/select.h" //Here is the problem for debugging
#ifdef PRINT
PrintVector(array, n);
#endif
}
includes.h
#include "../src/radixsortlsd.cpp"
#include "../src/radixsortmsd.cpp"
#include "../src/mergesort.cpp"
#include "../src/bitonicsort.cpp"
#include "../src/insertion.cpp"
#include "../src/slowsort.cpp"
#include "../src/selection.cpp"
select.h This is the code I want to debug. I decided to separate it from the main because it will grow a lot.
// The calls to CheckTime takes the first parameter as the direction to a function, previously defined inside the cpps of includes.h
#ifdef RADIXSORTLSD
CheckTime(&RadixSortLSD, array, n);
#endif
#ifdef RADIXSORTMSD
CheckTime(&RadixSortMSD, array, n);
#endif
#ifdef MERGESORT
CheckTime(&MergeSort, array, n);
#endif
#ifdef INSERTION
CheckTime(&Insertion, array, n);
#endif
#ifdef SLOWSORT
CheckTime(&SlowSort, array, n);
#endif
#ifdef SELECTION
CheckTime(&Selection, array, n);
#endif
#ifdef BITONICSORT
CheckTime(&BitonicSort, array, n);
#endif
I hope this help. Note that everything compiles great and works great (I made sure that the macros I defined when compiling are the correct ones)
Note: By debugging (not the right word) I meant checking how a function works (a function I don't fully understand).
Possibly you could break at MyFunction(), then run 'bt' command to see the stack. Then you see, is there any additional stack frame or what stack frames consist of in terms of source files, it might help
First of all:
A include is a preprocessor directive which never generates code. Debuggers can stop only on things which can be executed. Including a file works during compilation, not during runtime.
The next:
Your included files will define some values, functions, classes and a lot other. So you must give the debugger an idea where to stop.
And at all:
Including 'cpp' files is really trash! There are only very seldom reasons to do this.
But ok, how to proceed:
If your header file ( or included cpp file ) provides a function, you simply can do a break Func and run your program. No need to open any file in a gui for gdb before.
If you want to look inside the included files, you also can list myheader.h:1. The 1 one is the line of code you want to start looking into the file.
And a hint: Please provide much smaller code examples which persons can compile for themselves to give you more detailed help. You example is really bad to understand!
Example session:
Header: f.h
#include <stdlib.h>
void g(void)
{
malloc(4000);
}
void f(void)
{
malloc(2000);
}
main.cpp:
#include "f.h"
int main(void)
{
int i;
int* a[10];
for (i = 0; i < 10; i++) {
a[i] = (int*)malloc(1000);
}
f();
g();
for (i = 0; i < 10; i++) {
free(a[i]);
return 0;
}
}
Example session:
> gdb prog
gdb) break f
Breakpoint 1 at 0x40061a: file main.cpp, line 10.
(gdb) run
Starting program: /home/xxx/go
Breakpoint 1, f () at f.h:10
10 malloc(2000);
(gdb) list
5 malloc(4000);
6 }
7
gdb )
Now you can walk through your subroutine with step.

M_PI flagged as undeclared identifier

When I compile the code below, I got these error messages:
(Error 1 error C2065: 'M_PI' : undeclared identifier
2 IntelliSense: identifier "M_PI" is undefined)
What is this?
#include <iostream>
#include <math.h>
using namespace std;
double my_sqrt1( double n );`enter code here`
int main() {
double k[5] = {-100, -10, -1, 10, 100};
int i;
for ( i = 0; i < 5; i++ ) {
double val = M_PI * pow( 10.0, k[i] );
cout << "n: "
<< val
<< "\tmysqrt: "
<< my_sqrt1(val)
<< "\tsqrt: "
<< sqrt(val)
<< endl;
}
return 0;
}
double my_sqrt1( double n ) {
int i;
double x = 1;
for ( i = 0; i < 10; i++ ) {
x = ( x + n / x ) / 2;
}
return x;
}
It sounds like you're using MS stuff, according to their docs
Math Constants are not defined in Standard C/C++. To use them, you must first define _USE_MATH_DEFINES and then include cmath or math.h.
So you need something like
#define _USE_MATH_DEFINES
#include <cmath>
as a header.
math.h does not define M_PI by default.
So go with this:
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
This will handle both cases either your header have M_PI defined or not.
M_PI is supported by GCC too, but you've to do some work to get it
#undef __STRICT_ANSI__
#include <cmath>
or if you don't like to pollute your source file, then do
g++ -U__STRICT_ANSI__ <other options>
As noted by shep above you need something like
#define _USE_MATH_DEFINES
#include <cmath>
However you also include iostream.
iostream includes a lot of stuff and one of those things eventually includes cmath. This means that by the time you include it in your file all the symbols have already been defined so it is effectively ignored when you include it and the #define _USE_MATH_DEFINES doesn't work
If you include cmath before iostream it should give you the higher precision constants like M_PI
#define _USE_MATH_DEFINES
#include <cmath>
#include <iostream>
Use this include for Windows 10 (and Windows 11):
#include <corecrt_math_defines.h>
I used C99 in NetBeans with remote linux host with its build tools.
Try adding #define _GNU_SOURCE and add the -lm during linking.
You must use _USE_MATH_DEFINES before other headers like this:
#define _USE_MATH_DEFINES
#include <cmath>
#incude other headers...

Enable Boost.Log only on debug

I need a logger for debug purpose and I'm using Boost.Log (1.54.0 with a patch in the boost.org homepage).
It's all fine I've created some macro like this:
#define LOG_MESSAGE( lvl ) BOOST_LOG_TRIVIAL( lvl )
Now is that a way that LOG_MESSAGE( lvl ) is expaneded in BOOST_LOG_TRIVIAL( lvl ) only in debug mode and ignore in release?
for example:
LOG_MESSAGE( critical ) << "If I read this message we're in debug mode"
edit
My first attempt is to create a nullstream... I think that in release mode compiler will optimize it...
#if !defined( NDEBUG )
#include <boost/log/trivial.hpp>
#define LOG_MESSAGE( lvl ) BOOST_LOG_TRIVIAL( lvl )
#else
#if defined( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-value"
#endif
#include <iosfwd>
struct nullstream : public std::ostream {
nullstream() : std::ios(0), std::ostream(0) {}
};
static nullstream g_nullstream;
#define LOG_MESSAGE( lvl ) g_nullstream
#if defined( __GNUC__ )
#pragma GCC diagnostic pop
#endif
#endif
The severity level of the log entry meerly acts as a filter for sinks. The sink will decide what to do with the message (print it or not) based on the severity level. But the message will still be sent.
If you are trying to not send the message at all, then you'll need to redefine LOG_MESSAGE to something which actually does nothing. there might be something in the Boost library for this, otherwise, you'll have to write your own. Perhaps this will be a start:
class NullLogger
{
public:
template <typename SeverityT> NullLogger (SeverityT) {};
template <typename Val> NullLog& operator<< (const Val&) { return * this};
};
...and then:
#define LOG_MESSAGE (lvl) NullLogger (lvl)
Note however that even though nothing is being done with the log message or the expressions that make it up, the expressions are still evaluated. If some of these expressions are expensive, you will still take the performance hit. For example:
LOG_MESSAGE (debug) << SomeSuperExpensiveFunction();
Even if you are using the NullLogger above, SomeSuperExpensiveFunction() is still going to be called.
I would suggest as an alternative adding a flag that is evaluated at runtime, and decide at runtime whether or not to do the logging:
if (mLogStuff)
{
LOG_MESSAGE (debug) << SomeSuperExpensiveFunction();
}
boolean comparisons are super cheap, and you may find one day in the future that the ability to turn logging on and off could be super handy. Also, doing this means you don't need to add yet another #define, which is always a good thing.
I like John's NullLogger class. The only change I would make is as follows
#define LOG_MESSAGE(lvl) while (0) NullLogger (lvl)
Unfortunately this may generate warnings, but I would hope a decent compiler would then be able to eliminate all the associated logging code.
It is possible to achieve this without defining a NullLogger or similar:
#define TEST_LOG(lvl) \
if constexpr(boost::log::trivial::lvl >= boost::log::trivial::MAX_LOG_LEVEL) \
BOOST_LOG_TRIVIAL(lvl)
Then compile with -DMAX_LOG_LEVEL=info to statically deactivate all log messages below info.
Also note that with a properly implemented macro (like TEST_LOG but also like BOOST_LOG_TRIVIAL) expensive functions are not evaluated:
// We either log with trace or warning severity, so this filter
// does not let any message pass
logging::core::get()->set_filter(
logging::trivial::severity >= logging::trivial::error);
// Filtered at compile time
{
auto start = std::chrono::steady_clock::now();
for (size_t i = 0; i < 1000 * 1000; i++) {
TEST_LOG(trace) << "Hello world!";
}
auto end = std::chrono::steady_clock::now();
std::cerr << std::chrono::duration<double>(end-start).count() << "s" << std::endl;
// Prints: 1.64e-07s
}
// Filtered at compile time
{
auto start = std::chrono::steady_clock::now();
for (size_t i = 0; i < 1000 * 1000; i++) {
TEST_LOG(trace) << ComputeExpensiveMessage();
}
auto end = std::chrono::steady_clock::now();
std::cerr << std::chrono::duration<double>(end-start).count() << "s" << std::endl;
// Prints: 8.5e-08s
}
// Filtered at run time
{
auto start = std::chrono::steady_clock::now();
for (size_t i = 0; i < 1000 * 1000; i++) {
TEST_LOG(warning) << "Hello world!";
}
auto end = std::chrono::steady_clock::now();
std::cerr << std::chrono::duration<double>(end-start).count() << "s" << std::endl;
// Prints: 0.249306s
}
// Filtered at run time
{
auto start = std::chrono::steady_clock::now();
for (size_t i = 0; i < 1000 * 1000; i++) {
TEST_LOG(warning) << ComputeExpensiveMessage();
}
auto end = std::chrono::steady_clock::now();
std::cerr << std::chrono::duration<double>(end-start).count() << "s" << std::endl;
// Prints: 0.250101s
}
John's NullLogger class doesn't compile correctly on MSVC, and still requires Boost dependency for SeverityT which is actually not needed.
I propose the following change to the class:
class NullLogger
{
public:
template <typename Val> NullLogger& operator<< (const Val&) { return *this; };
};
#define BOOST_LOG_TRIVIAL(lvl) NullLogger()