I'm using the UnitTest++ framework to implement unit tests on some C code I'm responsible for. The end product is embedded and uses const structures to hold configuration information. Since the target host can modify the configuration asynchronously the members of the structure are all volatile. Some of the structures are also declared as volatile.
I'm getting segmentation faults when I use const_cast to try to modify the structure instances lacking the volatile keyword on the UnitTest Windows 7 host. This makes sense to me. However, if the structure instance was declared with the volatile keyword then the test passes. This does not make sense to me.
Here's a quick code example that shows the problem with gcc on Win7. Switching the define value causes the segfault to appear or not, depending on if the volatile instance of the struct is used or not.
typedef struct
{
volatile int foo;
volatile int bar;
} TestStruct;
const TestStruct constStruct = { 1, 2};
volatile const TestStruct volatileConstStruct = { 3, 4};
#define SEG_FAULT 0
int main(void)
{
TestStruct * constPtr = const_cast<TestStruct*>(&constStruct);
TestStruct * constVolPtr = const_cast<TestStruct*>(&volatileConstStruct);
#if(SEG_FAULT == 0)
constVolPtr->foo = 10;
#else
constPtr->foo = 20;
#endif
}
Can anyone help me understand why the volatile keyword presents a workaround for the segfault? Also, can anyone suggest a method to allow me to modify the values in the structure for unit test without adding the volatile keyword to all the structure instances?
EDIT:
I've just discovered that you can do this in C:
#define const
Including the effective "const undefine" above in the test fixture allows my target compiler to see the const keyword and correctly place the structures into flash memory. However, the preprocessor on the UnitTest++ compiler strips out the const keyword, so my test fixture is able to modify the struct.
The drawback to this solution is that I cannot add unit tests that verify correct const operation of function calls. However, since removing the const from the struct instances is not an option (need the data to be placed in flash) this appears to be a drawback I will have to live with.
Why this strange behavior?
Modifying a const object using const_cast is an Undefined Behavior.
const_cast is used when you have a const pointer to an non const object and you want to point your pointer to it.
Why it works with volatile?
Not sure. However, It is still an Undefined Behavior and you are just lucky that it works.
The problem with Undefined Behavior is that all safe bets are off and the program might show any behavior. It might appear to work or it may not work. may crash or show any weird behavior.
it is best to not write any code exhibiting Undefined Behavior, that saves warranting explanations for such situations.
How to solve this?
Don't declare the objects you modify as const, Since you intend to modify them during the course of your program/test, they should not be const. Currently, You are making a promise to the compiler that your structure objects are immutable(const) but later you break that contract by modifying it. Make this promise only if you can keep it.
I believe a footnote in the standard gives you the answer. (Note that footnotes are not normative.)
In §6.7.3 of the standard draft N1570:
132) The implementation may place a const object that is not volatile
in a read-only region of storage.
This mean that the structure defined with the volatile keyword will be placed in read-write memory, despite the fact that it's defined const.
One could argue that the compiler is not allowed to place any of the structures in read-only memory, as they both contains volatile members. I would send in a compiler bug report, if I were you.
Can anyone help me understand why the volatile keyword presents a
workaround for the segfault? Also, can anyone suggest a method to
allow me to modify the values in the structure for unit test without
adding the volatile keyword to all the structure instances?
You can't. A const object is placed in read-only memory, and you will trigger a segfault if you write to it. Either drop the const or add volatile -- I would strongly recommend dropping const.
Related
By using the const qualifier a variable is supposed to be made read-only. As an example, an int marked const cannot be assigned to:
const int number = 5; //fine to initialize
number = 3; //error, number is const
At first glance it looks like this makes it impossible to modify the contents of number. Unfortunately, actually it can be done. As an example const_cast could be used (*const_cast<int*>(&number) = 3). This is undefined behavior, but this doesn't guarantee that number does not actually get modified. It could cause the program to crash, but it could also simply modify the value and continue.
Is it possible to make it actualy impossible to modify a variable?
A possible need for this might be security concerns. It might need to be of highest importance that some very valuable data must not be changed or that a piece of data being sent must not be modified.
No, this is not the concern of a programming language. Any "access" protection is only superficial and only exists at compile-time.
Memory of a computer can always be modified at runtime if you have the corresponding rights. Your OS might provide you with facilities to secure pages of memory though, e.g VirtualProtect() under Windows.
(Notice that an "attacker" could use the same facilities to restore the access if he has the privilege to do so)
Also I assume that there might be hardware solutions for this.
There is also the option of encrypting the data in question. Yet it appears to be a chicken-and-egg situation as the private key for the encryption and decryption has to be stored somewhere in memory as well (with a software-only solution).
While most of the answers in this thread are correct, but they are related to const, while the OP is asking for a way to have a constant value defined and used in the source code. My crystal ball says that OP is looking for symbolic constants (preprocessor #define statements).
#define NUMBER 3
//... some other code
std::cout<<NUMBER;
This way, the developer is able to parametrize values and maintain them easily, while there's virtually no (easy) way to alter it once the program is compiled and launched.
Just keep in mind that const variables are visible to debuggers, while symbolic constants are not, but they require no additional memory. Another criteria is the type checking, which is absent in case of symbolic constants, as well as for macros.
const is not intended to make a variable read-only.
The meaning of const x is basically:
Hey compiler, please prevent me from casually writing code in this scope which changes x.
That's very different from:
Hey compiler, please prevent any changes to x in this scope.
Even if you don't write any const_cast's yourself - the compiler will still not assume that const'ed entities won't change. Specifically, if you use the function
int foo(const int* x);
the compiler cannot assume that foo() doesn't change the memory pointed to by x.
You could use your value without a variable
Variables vary... so, naturally, a way to prevent that is using values which aren't stored in variables. You can achieve that by using...
an enumeration with a single value: enum : int { number = 1 }.
the preprocessor: #define NUMBER 1 <- Not recommended
a function: inline int get_number() { return 1; }
You could use implementation/platform-specific features
As #SebastianHoffman suggests, typical platforms allow marking some of a process' virtual memory space as read-only, so that attempts to change it result in an access violation signal to the process and the suspension of its execution. This is not a solution within the language itself, but it is often useful. Example: When you use string literals, e.g.:
const char* my_str = "Hello world";
const_cast<char*>(my_str)[0] = 'Y';
Your process will likely fail, with a message such as:
Segmentation fault (core dumped)
If you know the program at compile-time, you can place the data in read-only memory. Sure, someone could get around this, but security is about layers rather than absolutes. This makes it harder. C++ has no concept of this, so you'll have to inspect the resulting binary to see if it's happened (this could be scripted as a post-build check).
If you don't have the value at compile-time, your program depends on being able to change / set it at runtime, so you fundamentally cannot stop that from happening.
Of course, you can make it harder though things like const so the code is compiled assuming it won't change / programmers have a harder time accidentally changing it.
You may also find constexpr an interesting tool to explore here.
There is no way to specify what code does that does not adhere to the specification.
In your example number is truly constant. You correctly note that modifiying it after a const_cast would be undefined beahvior. And indeed it is impossible to modify it in a correct program.
As the tile implies, in C++ we cannot have contains that hold references since objects inside containers have to be assignable. We cannot reassign a reference after it's been initialized.
However, in my program, I have a static const std::map that holds const reference as values and it compiles fine. I am wondering if the reason is because the map is declared as const and initialized at declaration, which tells the compiler that "this object is const and its content will not change so it's ok to hold const reference as its values".
I couldn't find answers anywhere else. The code works but I don't want it to confuse other developers.
Edit,
Sorry I didn't include the code. Here it goes:
const glm::dvec4& GetObjectColor(const msg::ObjectType type) {
static const std::map<msg::ObjectType, const glm::dvec4&> kObjectColorMap = {
{msg::ObjectType::PERSON, kWhite},
{msg::ObjectType::ANIMAL, kSilver},
{msg::ObjectType::SEDAN, kGray},
{msg::ObjectType::SUV, kRed},
{msg::ObjectType::VAN, kMaroon},
{msg::ObjectType::BICYCLE, kYellow},
{msg::ObjectType::TRICYCLE, kOlive},
{msg::ObjectType::MOTORCYCLE, kLime},
{msg::ObjectType::TRUCK, kGreen},
{msg::ObjectType::BUS, kAqua},
{msg::ObjectType::PICKUP, kTeal},
{msg::ObjectType::UNKNOWN, kBlue}};
return kObjectColorMap.at(type);
}
No. You cannot.
Maybe you have seen this question already: Why does storing references (not pointers) in containers in C++ not work?
The premise of the quesiton is correct. You cannot store reference in containers.
... and it compiles fine.
Code not causing a compiler error cannot safely assumed to be correct. Actually "compiles without errors" is the lowest bar you can put on code. Consider this horribibly broken code:
int* dont_do_this_at_home;
*dont_do_this_at_home = 42; // serisouly: DONT DO THIS
No compiler I know will issue an error or warning for this code irrespective of the fact that this code could not be more broken. The best that can happen here is that you get a segmentation fault. The worst: Demons fly out of your nose. Read here about undefined behavior: https://en.cppreference.com/w/cpp/language/ub
As explained in the above linked Q&A, the language specs say: you cannot store reference in containers. If you still do it and your compiler will not generate an error, then you should not assume that you found a way around the rule.
It is similar to not being allow to toucht the ball with your hands in soccer. You can touch the ball with your hands, but that does not disprove the rule.
Consider this:
int a = 5;
std::map<int,int&> x{ { 1,a} }; // WRONG !!!
No compiler error, but still it is wrong. C++ isnt soccer, if you break the rules there is no referee that will tell you about it.
PS: there is std::reference_wrapper to store references in containers.
I know for a function this simple it will be inlined:
int foo(int a, int b){
return a + b;
}
But my question is, can't the compiler just auto-detect that this is the same as:
int foo(const int a, const int b){
return a + b;
}
And since that could be detected, why would I need to type const anywhere? I know that the inline keyword has become obsolete because of compiler advances. Isn't it time that const do the same?
You don't put const as the result of not modifying a variable. You use const to enforce you not modifying it. Without const, you are allowed to modify the value. With const, the compiler will complain.
It's a matter of semantics. If the value should not be mutable, then use const, and the compiler will enforce that intention.
Yes, the compiler can prove constness in your example.
No, it would be of no use :-).
Update: Herb Sutter dedicated one of his gotchas to the topic (http://www.gotw.ca/gotw/081.htm). Summary:
const helps most by making the compiler and linker choose functions for const objects including const member functions which can be coded to be more efficient.
const doesn't help with the usual translation unit model [differs from what I supposed]; the compiler needs to see the whole program for verifying factual constness (which the mere declaration does not guarantee) and exploiting it, as well as prove the absence of aliasing ...
... and when the compiler can see the whole program and can prove factual constness it actually of course doesn't need the const declaration any longer! It can prove it. Duh.
The one place where const makes a big difference is a definition because the compiler may store the object in read-only memory.
The article is, of course, worth reading.
With respect to whole program optimization/translation which usually is necessary to exploit constness cf. the comments below from amdn and Angew.
can't the compiler just auto-detect that this is the same as...
If by that you mean whether the compiler can detect that the variables are not modified in the second case, most likely yes. The compiler is likely to produce the same output for both code samples. However, const might help the compiler in more complex situations. But the most important point is that it keeps you from inadvertently modifying one of the variables.
The compiler will always know what you did and will infer internal constness from that in order to optimize the code.
What the compiler can never know is what you wanted to do.
If you wanted a variable to remain constant but accidentally change it later in the code the compiler can only trap this error if you tell the compiler what you wanted.
This is what the const keyword is for.
struct bar {
const int* x;
};
bar make_bar(const int& x){
return {&x};
}
std::map<int,bar> data;
shuffle(data);
knowing that bar will never modify x (or cause it to be modified) in its lifetime requires understanding every use of bar in the program, or, say, making x a pointer to const.
Even with perfect whole program optimization (which cannot exist: turing machines are not perfectly understandable), dynamic linking means you cannot know at compile time how data will be used. const is a promise, and breaking that promise (in certain contexts) can be UB. The compiler can use that UB to optimize in ways that ignores the promise being broken.
inline is not obsolete: it means the same thing it ever did, that linker collisions of this symbol are to be ignored, and it mildly suggests injecting the code into the calling scope.
const simplifies certain optimizations (which may make them possible), and enforces things on the programmer (which helps the programmer), and can change what code means (const overloading).
Maybe he could but the const statement is also for you. If you set a variable as const and try to assign a new value afterwards you will get an error. If the compiler would make a var out of it by himself this would not work.
Const qualifier is a method to enforce behavior of the variables inside your scope. It only provides the compiler the means to scream at you if you try to modify them inside the scope where they are declared const.
A variable might be truly const (meaning it is writen in a read only location, hence compiler optimizations) if it's const at the time of it's declaration.
You can provide your 2nd function non const variables who will become "const" inside the function scope.
Or alternativelly you can bypass the const by casting , so the compiler cannot parse your whole code in an attempt to figure out if the valuea will be changed or not inside the function scope.
Considering that const qualifiers are mainly for code enforcing, and that compilers will generate the same code in 99% of cases if a variable is const or non const, then NO, the compiler shouldn't auto-detect constness.
Short answer: because not all problems are that simple.
Longer answer: You cannot assume that an approach which works with a simple problem also works with a complex problem
Exact answer: const is an intent. The main goal of const is to prevent you doing anything accidentially. If the compiler would add const automatically it would just see that the approach is NOT const and leave it at it. Using the const keyword will raise an error instead.
This question already has answers here:
Does const-correctness give the compiler more room for optimization?
(7 answers)
Closed 9 years ago.
Do const declarations help the compiler (GCC) produce faster code or are they only useful for readability and correctness?
Zed Shaw has argued that const is useless or is overused in C/C++:
Next is all the bizarre fascination with const. For some odd reason
C++ loves to make you slap const on every part of a declaration, and
yet I get the same end result as C: a function is called. (...)
(From: http://librelist.com/browser//mongrel2/2010/7/15/c-verses-c++/#770d94bcfc6ddf1d8510199996b607dd )
Yes. Here’s one concrete example. const makes it possible to pass arguments by const& rather than by value (which might require a costly copy). It’s important to realise that the alternative to pass-by-const& is not pass-by-& because the latter doesn’t allow temporaries to be bound. So, for instance, this code:
auto result = foo{1} + foo{2} + foo{3};
may call foo operator +(foo const&, foo const&) but it may not call foo operator +(foo&, foo&).
That way, const helps avoid copies.
But generally, const is a tool to ensure correctness, not to to aid optimisations.
Either way, Zed Shaw has no idea what he’s talking about. The rest of his rant is similarly misinformed, by the way.
No, const does not help the compiler make faster code. Const is for const-correctness, not optimizations.
The C++ standard says that const items can't be modified, but also says that const_cast should remove the const modifier from an object and make it writable (unless it's located in actually read-only memory, in which case the behavior is undefined); as such const cannot mean, in general, that the target variable will not change.
I can only think of these two very narrow scenarios where having const produces faster code than not having it:
the variable is global with internal linkage (static) and is passed by reference or pointer to a function defined in a different translation unit (different file). In this case, the compiler cannot elide reads to it if it is not marked const;
the variable is global with external linkage (extern). Reads to a const extern can be elided inside the file that defines it (but nowhere else).
When const is applied to a global variable, the compiler is allowed to assume that the value will never change because it will place it in read-only memory, and this means undefined behavior if the program attempts to modify it, and compiler authors love to rely on the threat of undefined behavior to make code faster.
Note that both scenarios apply only to global variables, which probably make for a very minor portion of the variables in your program. To its merit, however, const implies static at the global level in C++ (this is not the case in C).
Someone above said that using const can make code faster because it's possible to use const references. I would argue here that what make the code faster is the use of a reference, not the use of const.
That said, I still believe const is a very sharp knife with which you can't cut yourself and I would advise that you use it whenever it's appropriate, but don't do it for performance reasons.
Yes, const can (not guaranteed) help the compiler produce faster/more correct code. More so than not, they're just a modifier on data that you express to both the compiler and to other people that read your code that some data is not supposed to change. This helps the type system help you write more correct software.
More important than optimizations, they just prevent your own code and people using your code from writing to data you assume to be invariant.
In general const modifier on method, references and pointers can't be used to optimize code for a couple of reasons. The primary one is that const modifier, in those contexts, doesn't make any guarantees about the underlying data not changing, it just makes it harder to modify it. Here is a classic example
void M(const C& p1, C& p2) {
cout << p1.field << endl;
p2.Mutate();
cout << p1.field<< endl;
}
In this case it's very possible that p1.field is modified in this code. The most obvious case is that p1 and p2 refer to the same value.
C local;
M(local, local);
Hence there is no real optimization the compiler can do here. The const parameter is equally as dangerous as the non-const one.
The other reason why it can't really optimize is that anyone can cheat in C++ with const_cast.
class C {
public:
int field;
int GetField() const {
C* pEvil = const_cast<C*>(this);
pEvil->field++;
return field;
}
};
So even if you are dealing with a single const reference the values are still free to change under the hood.
I often use const for local variables that are not being modified, like this:
const float height = person.getHeight();
I think it can make the compiled code potentially faster, allowing the compiler to do some more optimization. Or am I wrong, and compilers can figure out by themselves that the local variable is never modified?
Or am I wrong, and compilers can figure out by themselves that the local variable is never modified?
Most of the compilers are smart enough to figure this out themselves.
You should rather use const for ensuring const-correctness and not for micro-optimization.
const correctness lets compiler help you guard against making honest mistakes, so you should use const wherever possible but for maintainability reasons & preventing yourself from doing stupid mistakes.
It is good to understand the performance implications of code we write but excessive micro-optimization should be avoided. With regards to performance one should follow the,
80-20 Rule:
Identify the 20% of your code which uses 80% of your resources, through profiling on representative data sets and only then attempt to optimize those bottlenecks.
This performance difference will almost certainly be negligible, however you should be using const whenever possible for code documentation reasons. Often times, compilers can figure this out for your anyway and make the optimizations automatically. const is really more about code readability and clarity than performance.
If there is a value type on the left hand, you may safely assume that it will have a negligible effect, or none at all. It's not going to influence overload resolution, and what is actually const can easily be deduced from the scope.
It's an entirely different matter with reference types:
std::vector<int> v(1);
const auto& a = v[0];
auto& b = v[0];
These two assignments resolve to two entirely different operators, and similar overload pairs are found in many libraries aside STL too. Even in this simple example, optimizations which depend on v having been immutable for the scope of b are already no longer trivial and less likely to be found.
The STL is still quite tame in these terms though, in such that at least the behavior doesn't change based on choosing the const_reference overload or not. For most of STL, the const_reference overload is only tied to the object being const itself.
Some other libraries (e.g. Qt) make heavy use of copy-on-write semantics. In these const-correctness with references is no longer optional, but necessary:
QVector<int> v1(1);
auto v2 = v1; // Backing storage of v2 and v1 is still linked
const auto& a = v1[0]; // Still linked
const auto& b = v2[0]; // Still linked
auto& c = v2[0]; // Deep copy from v1 to v2 is happening now :(
// Even worse, &b != &c
Copy-on-write semantics are something commonly found in large-matrix or image manipulation libraries, and something to watch out for.
It's also something where the compiler is no longer able to save you, the overload resolution is mandated by C++ standard and there is no leeway for eliminating the costly side effects.
I don't think it is a good practice to make local variables, including function parameters, constant by default.
The main reason is brevity. Good coding practices allow you to make your code short, this one doesn't.
Quite similarly, you can write void foo(void) in your function declarations, and you can justify it by increased clarity, being explicit about not intending to pass a parameter to the function, etc, but it is essentially a waste of space, and eventually almost fell out of use. I think the same thing will happen to the trend of using const everywhere.
Marking local variables with a const qualifier is not very useful for most of the collaborators working with the code you create. Unlike class members, global variables, or the data pointed to a by a pointer, a local variable doesn't have any external effects, and no one would ever be restricted by the qualifier of the local variable or learn anything useful from it (unless he is going to change the particular function where the local variable is).
If he needs to change your function, the task should not normally require him to try to deduce valuable information from the constant qualifier of a variable there. The function should not be so large or difficult to understand; if it is, probably you have more serious problems with your design, consider refactoring. One exception is functions that implement some hardcore math calculations, but for those you would need to put some details or a link to the paper in your comments.
You might ask why not still put the const qualifier if it doesn't cost you much effort. Unfortunately, it does. If I had to put all const qualifiers, I would most likely have to go through my function after I am done and put the qualifiers in place - a waste of time. The reason for that is that you don't have to plan the use of local variables carefully, unlike with the members or the data pointed to by pointers.
They are mostly a convenience tool, technically, most of them can be avoided by either factoring them into expressions or reusing variables. So, since they are a convenience tool, the very existence of a particular local variable is merely a matter of taste.
Particularly, I can write:
int d = foo(b) + c;
const int a = foo(b); int d = a + c;
int a = foo(b); a += c
Each of the variants is identical in every respect, except that the variable a is either constant or not, or doesn't exist at all. It is hard to commit to some of the choices early.
There is one major problem with local constant values - as shown in the code below:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
// const uint32_t const_dummy = 0;
void func1(const uint32_t *ptr);
int main(void) {
const uint32_t const_dummy = 0;
func1(&const_dummy);
printf("0x%x\n", const_dummy);
return EXIT_SUCCESS;
}
void func1(const uint32_t *ptr) {
uint32_t *tmp = (uint32_t *)ptr;
*tmp = 1;
}
This code was compiled on Ubuntu 18.04.
As you can see, const_dummy's value can be modified in this case!
But, if you modify the code and set const_dummy scope to global - by commenting out the local definition and remove the comment from the global definition - you will get an exception and your our program will crash - which is good, because you can debug it and find the problem.
What is the reason? Well global const values are located in the ro (read only) section of the program. The OS - protects this area using the MMU.
It is not possible to do it with constants defined in the stack.
With systems that don't use the MMU - you will not even "feel" that there is a problem.