Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Coding style conformance

...

In this noncompliant code example, a const-qualified method is called, which attempts to cache results by casting away the const-qualifier of this. Because s was declared const, the mutation of CachedCalc cachedCalc results in undefined behavior.

Code Block
bgColor#FFcccc
langcpp
#include <iostream>
 
class S {
  int CachedCalccachedCalc;
  
  int expensiveComputeexpensive_compute() const;  
public:
  S() : CachedCalccachedCalc(0) {}
  
  // ...  
  int Calculatecalculate() const {
    if (!CachedCalccachedCalc) {
      const_cast<S *>(this)->CachedCalc>cachedCalc = expensiveComputeexpensive_compute();  
    }        
    return CachedCalccachedCalc;
  }
};

void f() {
  const S s;
  std::cout << s.Calculatecalculate() << std::endl;
}

Compliant Solution

This compliant solution uses the mutable keyword when declaring CachedCalccachedCalc, which allows it to be mutated within a const context without triggering undefined behavior:

Code Block
bgColor#ccccff
langcpp
#include <iostream>
 
class S {
  mutable int CachedCalccachedCalc;
  
  int expensiveComputeexpensive_compute() const;
public:
  S() : CachedCalccachedCalc(0) {}
  
  // ...  
  int Calculatecalculate() const {
    if (!CachedCalccachedCalc) {
      CachedCalccachedCalc = expensiveComputeexpensive_compute();  
    }        
    return CachedCalccachedCalc;
  }
};

void f() {
  const S s;
  std::cout << s.Calculatecalculate() << std::endl;
}

Noncompliant Code Example

...

Code Block
// Legacy function defined elsewhere - cannot be modified; does not attempt to
// modify the contents of the passed parameter.
void audit_log(char *errstr);

void f() {
  const char INVFNAME[]  = "Invalid file name.";
  audit_log(const_cast<char *>(INVFNAME)); // EXP35-EX1
}

Risk Assessment

If the object is declared as being constant, it may reside in write-protected memory at runtime. Attempting to modify such an object may lead to abnormal program termination or a denial-of-service attack. If an object is declared as being volatile, the compiler can make no assumptions regarding access of that object. Casting away the volatility of an object can result in reads or writes to the object being reordered, or elided entirely, resulting in abnormal program execution.

...