8

The following code compile well both with GCC (4.2-4.6) and with Clang (2.1), but when I run the executable it gives me "Bus error: 10". I don't understand the reason.

#include <iostream>

struct A
{
  static int const v;
  A() { ++*const_cast<int *>(&A::v); }
};

int const A::v = 0;

int main(int argc, char * argv[])
{
  A a, b, c;
  std::cout << a.v << std::endl;

  return 0;
}
mattia.penati
  • 532
  • 5
  • 18
  • 3
    I'm pretty sure that modifying something that you declare const is undefined behaviour, but I'm sure someone can dig up the precise statement. – Kerrek SB Aug 08 '11 at 19:33
  • 3
    +1 for providing a minimal complete sample program. For more information, see http://sscce.org/. – Robᵩ Aug 08 '11 at 19:39

7 Answers7

12

I think the relevant quote is:

§ 7.1.6.1 (4) from N3242:

Except that any class member declared mutable can be modified, any attempt to modify a const object during its lifetime results in undefined behavior.

The examples illustrate the point using const_cast. As James pointed out: the quote can be found in §7.1.5 in the C++03 standard.

A little elaboration: That language rule allows the compiler to use read-only memory (if it is available on the target architecture) when something is declared const. Without this rule const-ness could always be casted away without fearing any consequences and using it would only be a matter of developer discipline. The way it is you can at least tell people that they are invoking UB, which usually is a good deterrent. The const_cast itself is of minor relevance as it does not matter how you trick the compiler in letting you manipulate a const object.

Community
  • 1
  • 1
pmr
  • 58,701
  • 10
  • 113
  • 156
7

5.2.11.7:

Depending on the type of the object, a write operation through the pointer, lvalue or pointer to data member resulting from a const_cast that casts away a const-qualifier) may produce undefined behavior (7.1.5.1)

In your case, you are trying to modify data that is in read-only segment.

4

Because you're not allowed to modify variables declared as const.

john
  • 85,011
  • 4
  • 57
  • 81
2

I don't have a solution for the actual problem. I just can say, don't use const_cast unless the intention is to call a const member function from a non-const member function and "const_cast" the const result (to make it a mutable result for the non-const member function).

But I have a proposal for improving your design:

class A
{
private:
  static int v;
public:
  A() { ++v; }
  static int get_v() { return v; }
};

int A::v = 0;

int main(int argc, char * argv[])
{
  A a, b, c;
  std::cout << a.get_v() << std::endl;

  return 0;
}
Flinsch
  • 4,296
  • 1
  • 20
  • 29
2

Just because you've cast away const, doesn't mean that you will succeed in writing to that memory.

All that const_cast<T> does is remove the const-ness of the variable from the compiler's perspective. That lets the compiler go ahead and emit code to write to the variable. But at runtime, if the compiler/linker happened to put the variable in read-only memory, then the hardware will stop you writing there no matter how you cast it.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
2

Basically, if a variable is declared const, the compiler is allowed to emit the results to read only memory. Taking a pointer/reference to a const object and then using const_cast to remove the const can result in undefined behavior.

In general, it is only safe to use const_cast if the object being refered to is non-const (even if the pointer/reference you have is const).

Dave S
  • 20,507
  • 3
  • 48
  • 68
1

The problem is this line :

static int const v;

Because you declared it const, the const_cast is causing an undefined behaviour - in your case you are lucky with getting bus error (it is a segmentation fault on my system).

Declare it non-const, and you can call const_cast on it without problems.

BЈовић
  • 62,405
  • 41
  • 173
  • 273