Main Content

AUTOSAR C++14 Rule A17-1-1

Use of the C Standard Library shall be encapsulated and isolated

Since R2021a

Description

Rule Definition

Use of the C Standard Library shall be encapsulated and isolated.

Rationale

The C Standard Library functions leave the responsibility for handling errors, data races and security issues to developers. For instance, some C Standard Library functions return specific values on errors. A developer calling one of those functions has to explicitly check its return value for those errors.

If all calls to C Standard Library functions are isolated and encapsulated in wrapper functions, the wrapper functions can be left to perform the checking. Callers of those wrapper functions are freed from the responsibility of handling specific error values from the C Standard Library function calls. Instead, the callers can handle errors from the wrapper function calls like any other exception.

Polyspace Implementation

The checker flags functions that contain a call to a C Standard Library function and one of these C++-specific constructs:

  • A call to a C++ Standard Library function.

  • A try block.

  • A new or delete operator.

  • Range-based for loops.

These C++-specific constructs indicate that the call to the C Standard Library function is not fully encapsulated and isolated. The event list below a rule violation shows the locations of the C Standard Library function call and the C++-specific construct.

Note that when C Standard Library functions are redeclared in the std namespace, their specifications remain unchanged. The rationale for encapsulating continues to apply to std:: versions of the C library functions. Therefore, the checker flags these versions, too.

Troubleshooting

If you expect a rule violation but Polyspace® does not report it, see Diagnose Why Coding Standard Violations Do Not Appear as Expected.

Examples

expand all

#include <cerrno>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <stdexcept>

void func1() { //Compliant
    FILE* fptr;
    fptr = fopen("myfile.txt", "w");
    // C-style error handling
    if (fptr == NULL) {
        throw std::system_error(errno, std::system_category()); 
    }
    
    fclose(fptr);
}

void func1_caller() noexcept{
    // C++-style error handling
    try {
        func1();
    }
    catch(std::system_error& e) {
        std::cerr << "Error "<< e.code() << ": " << e.what();
    }
}

std::int32_t func2() { //Noncompliant
    FILE* fptr;
    fptr = fopen("myfile.txt", "w");
    // C-style error handling
    if (fptr == NULL) {
        std::cerr << "Error " << strerror(errno);
        return errno;
    }
    
    // C++-style error handling
    try {
        fclose(fptr);       
    }
    catch (std::exception& e) {
        fclose(fptr);
    }
    return errno;
}

In this example, the call to the C Standard Library function fopen() is encapsulated in the wrapper function func1(). The wrapper function performs all the error handling required after the call. Functions calling func1(), for instance, func1_caller(), do not have to concern themselves about the fopen() errors and can handle exceptions from func1() like other exceptions.

Conversely, the function func2() does not fully encapsulate the fopen() call and returns the value of errno. Note that fopen() sets the value of errno after errors. Callers of func2() have to read the errno value via the func2() return and if the value indicates an error, perform any resource cleanup required.

The use of the try block in func2() indicates that the fopen() call is not fully isolated and encapsulated.

Check Information

Group: Library introduction
Category: Required, Non-automated

Version History

Introduced in R2021a