Assign a value to a variable at compilation time - c++

I'd like to assign a specific value to a variable when my code is compiling (for C and C++):
For example having :
//test.c
int main()
{
int x = MYTRICK ; (edit: changed __MYTRICK__ to MYTRICK to follow advices in comment)
printf ("%d\n", x);
return 0;
}
beeing able to do something like:
gcc -XXX MYTRICK=44 test.c -o test
and having as a result :
$./test
44

Use -D option:
gcc -DMYTRICK=44 test.c -o test
And use MYTRICK macro in your program and not __MYTRICK__. Names beginning with __ are reserved by the implementation.

Related

constexpr function which is shared in multiple modules

I noticed a strange behavior when I was working with a constexpr function.
I reduced the code to a simplified example.
Two functions are called from two different translation units (module A and B).
#include <iostream>
int mod_a();
int mod_b();
int main()
{
std::cout << "mod_a(): " << mod_a() << "\n";
std::cout << "mod_b(): " << mod_b() << "\n";
std::cout << std::endl;
return 0;
}
The modules look similar. This is mod_a.cpp:
constexpr int X = 3;
constexpr int Y = 4;
#include "common.h"
int mod_a()
{
return get_product();
}
Only some internal constants differ. This is mod_b.cpp:
constexpr int X = 6;
constexpr int Y = 7;
#include "common.h"
int mod_b()
{
return get_product();
}
Both modules use a common constexpr function which is defined in "common.h":
/* static */ constexpr int get_product()
{
return X * Y;
}
I was very astonished that both functions return 12. Due to the #include directive (which should only be some source code inclusion), I supposed that there is no interaction between both modules.
When I defined get_product also to be static, the behavior was as expected:
mod_a() returned 12,
mod_b() returned 42.
I also looked Jason Turner's episode 312 of C++ Weekly: Stop Using 'constexpr' (And Use This Instead!) at https://www.youtube.com/watch?v=4pKtPWcl1Go.
The advice to use generally static constexpr is a good hint.
But I still wonder if the behavior which I noticed without the static keyword is well defined. Or is it UB? Or is it a compiler bug?
Instead of the constexpr function I also tried a C-style macro #define get_product() (X*Y) which showed me also the expected results (12 and 42).
Take care
michaeL
This program ill-formed: X and Y have internal linkage since they are const variables at namespace scope. This means that both definitions of constexpr int get_product() (which is implicitly inline) violate the one definition rule:
There can be more than one definition in a program of each of the following: [...], inline function, [...], as long as all the following is true:
[...]
name lookup from within each definition finds the same entities (after overload-resolution), except that
constants with internal or no linkage may refer to different objects as long as they are not odr-used and have the same values in every definition
And obviously these constants have different values.
What's happening is both mod_a and mod_b are calling get_product at runtime. get_product is implicitly inline, so one of the definitions is chosen and the other is discarded. What gcc seems to do is take the first definition found:
$ g++ mod_a.cpp mod_b.cpp main.cpp && ./a.out
mod_a(): 12
mod_b(): 12
$ g++ mod_b.cpp mod_a.cpp main.cpp && ./a.out
mod_a(): 42
mod_b(): 42
$ g++ -c mod_a.cpp
$ g++ -c mod_b.cpp
$ g++ mod_a.o mod_b.o main.cpp && ./a.out
mod_a(): 12
mod_b(): 12
$ g++ mod_b.o mod_a.o main.cpp && ./a.out
mod_a(): 42
mod_b(): 42
It's as if get_product isn't constexpr, since it is getting called at runtime.
But if you were to enable optimisations (or force get_product() to be called at compile time, like with constexpr int result = get_product(); return result;), the results are as you would "expect":
$ g++ -O1 mod_a.cpp mod_b.cpp main.cpp && ./a.out
mod_a(): 12
mod_b(): 42
(Though this is still UB, and the correct fix is to make the functions static)
This code violates the One Definition Rule (language lawyers please correct me if I'm wrong).
If I compile the code separately, I get the behavior that you expect:
g++ -O1 -c main.cpp
g++ -O1 -c mod_a.cpp
g++ -O1 -c mod_b.cpp
g++ *.o
./a.out
> mod_a(): 12
> mod_b(): 42
If I compile all at once or activate link-time optimization, the UB becomes apparent.
g++ -O1 *.cpp
./a.out
> mod_a(): 12
> mod_b(): 12
How to fix this
You are on the right track with declaring them static. More C++-esce would be an anonymous namespace. You should also declare the constants static or put them in a namespace, not just the function.
mod_a.cpp:
namespace {
constexpr int X = 3;
constexpr int Y = 4;
}
#include "common.h"
int mod_a()
{
return get_product();
}
common.h:
namespace {
constexpr int get_product()
{
return X * Y;
}
} /* namespace anonymous */
Even better, in my opinion: Include the common.h within an opened namespace. That makes the connection between the declarations more apparent and would allow you to have multiple public get_products, one per namespace. Something like this:
mod_a.cpp:
namespace {
constexpr int X = 3;
constexpr int Y = 4;
#include "common.h"
} /* namespace anonymous */
int mod_a()
{
return get_product();
}

Ebpf:undefined symbol for helpers

I run an up to date debian testing (with kernel 4.19).
Helpers are not found on my system (but they exist in the header, Qt jumps to them)
#include "bpf/bpf.h"
int main (){
int r = bpf_create_map(BPF_MAP_TYPE_ARRAY,1,1,1,0);
return 0;
}
Compilation results in
undefined reference to `bpf_create_map(bpf_map_type, int, int, int, unsigned int)'
compiled with
g++ -c -pipe -g -std=gnu++1z -Wall -W -fPIC -DQT_QML_DEBUG -I. -I../../Qt/5.13.0/gcc_64/mkspecs/linux-g++ -o main.o main.cpp
g++ -lbpf -o server main.o
Same result with
g++ main.cpp -lbpf -o out
I have the libbpf-dev installed as well and i have the associated libraries (a and so).
What is wrong?
Update
even the following code won't work
#include <linux/bpf.h>
int main (){
//int r = bpf_create_map(BPF_MAP_TYPE_ARRAY,1,1,1,0);
bpf_attr attr = {};
attr.map_type = BPF_MAP_TYPE_ARRAY;
attr.key_size = 1;
attr.value_size = 1;
attr.max_entries = 1;
bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
return 0;
}
results in
error: 'bpf' was not declared in this scope
Update2:
BTW, key size is mandated to be 4 and not 1; but it is a point aside, that was unrelated to my problem here.
Namespace issue due to compiling in C++, you probably want:
extern "C" {
#include "bpf/bpf.h"
}
int main()...
Regarding your second error (error: 'bpf' was not declared in this scope), this is not directly related to libbpf, this is because there is no function simply called bpf() to actually perform the syscall. Instead you have to use the syscall number. For example, libbpf defines the following:
static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
unsigned int size)
{
return syscall(__NR_bpf, cmd, attr, size);
}
... and uses sys_bpf() after that, the same way you try to call bpf() in your sample.
For the record, “BPF helpers” often designates BPF functions that you call from within a BPF program, which is not the case here. Hence some confusion in the comments, I believe.

Stripping comments from c++ code while retaining line numbering

I'd like to strip the comments from a c++ file. This post provides the following solution for this:
gcc -fpreprocessed -dD -E test.c
However, this command appears to collapse long multiline comments. This causes behavior differences if the macro __LINE__ is used.
Can the gcc solution be salvaged to not change __LINE__-dependent behavior? Or, a non-gcc solution would work fine too.
Example test.c:
int main() {
/*
*
*
*
*
* comment 1
*/
// comment 2
return 0;
}
Output using gcc 4.9.2:
$ gcc -fpreprocessed -dD -E test.c
# 1 "test.c"
int main() {
# 10 "test.c"
return 0;
}
If we delete // comment 2, then we instead get the desired output without comment collapsing:
$ gcc -fpreprocessed -dD -E test.c
# 1 "test.c"
int main() {
return 0;
}
In GCC, the # directives with the numbers and file name correspond to line numbers, and thus maintain proper __LINE__ values.

How to trace out why gcc and g++ produces different code

Is it possible to see what is going on behind gcc and g++ compilation process?
I have the following program:
#include <stdio.h>
#include <unistd.h>
size_t sym1 = 100;
size_t *addr = &sym1;
size_t *arr = (size_t*)((size_t)&arr + (size_t)&addr);
int main (int argc, char **argv)
{
(void) argc;
(void) argv;
printf("libtest: addr of main(): %p\n", &main);
printf("libtest: addr of arr: %p\n", &arr);
while(1);
return 0;
}
Why is it possible to produce the binary without error with g++ while there is an error using gcc?
I'm looking for a method to trace what makes them behave differently.
# gcc test.c -o test_app
test.c:7:1: error: initializer element is not constant
# g++ test.c -o test_app
I think the reason can be in fact that gcc uses cc1 as a compiler and g++ uses cc1plus.
Is there a way to make more precise output of what actually has been done?
I've tried to use -v flag but the output is quite similar. Are there different flags passed to linker?
What is the easiest way to compare two compilation procedures and find the difference in them?
In this case, gcc produces nothing because your program is not valid C. As the compiler explains, the initializer element (expression used to initialize the global variable arr) is not constant.
C requires initialization expressions to be compile-time constants, so that the contents of local variables can be placed in the data segment of the executable. This cannot be done for arr because the addresses of variables involved are not known until link time and their sum cannot be trivially filled in by the dynamic linker, as is the case for addr1. C++ allows this, so g++ generates initialization code that evaluates the non-constant expressions and stores them in global variables. This code is executed before invocation of main().
Executables cc1 and cc1plus are internal details of the implementation of the compiler, and as such irrelevant to the observed behavior. The relevant fact is that gcc expects valid C code as its input, and g++ expects valid C++ code. The code you provided is valid C++, but not valid C, which is why g++ compiles it and gcc doesn't.
There is a slightly more interesting question lurking here. Consider the following test cases:
#include <stdint.h>
#if TEST==1
void *p=(void *)(unsigned short)&p;
#elif TEST==2
void *p=(void *)(uintptr_t)&p;
#elif TEST==3
void *p=(void *)(1*(uintptr_t)&p);
#elif TEST==4
void *p=(void *)(2*(uintptr_t)&p);
#endif
gcc (even with the very conservative flags -ansi -pedantic-errors) rejects test 1 but accepts test 2, and accepts test 3 but rejects test 4.
From this I conclude that some operations that are easily optimized away (like casting to an object of the same size, or multiplying by 1) get eliminated before the check for whether the initializer is a constant expression.
So gcc might be accepting a few things that it should reject according to the C standard. But when you make them slightly more complicated (like adding the result of a cast to the result of another cast - what useful value can possibly result from adding two addresses anyway?) it notices the problem and rejects the expression.

Array of size defined by not constant variable

There is such code:
#include <iostream>
int main()
{
int size;
std::cin >> size;
size = size + 1;
int tab3[size];
tab3[0] = 5;
std::cout << tab3[0] << " " << sizeof(tab3) << std::endl;
return 0;
}
The result is:
$ g++ prog.cpp -o prog -Wall -W
$ ./prog
5
5 24
Why does this code even compile? Shouldn't be length of array a constant variable?
I used g++ version 4.4.5.
Variable-length arrays in C++ are available as an extension in GCC. Compiling with all warnings should have alerted you to that fact (include -pedantic).
It is a C99 feature, not a part of C++. They are commonly refered to as VLAs(Variable Length Arrays.
If you run g++ with -pedantic it will be rejected.
See GCC docs for more info.
See also: VLAs are evil.
GCC provide's VLA's or variable length arrays. A better practice is to create a pointer and use the new keyword to allocate space. VLA's are not available in MSVC, so the second option is better for cross platform code