Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/MicrosoftDocs/cpp-docs/llms.txt

Use this file to discover all available pages before exploring further.

Static analysis examines your C++ source code for defects — buffer overruns, null pointer dereferences, uninitialized memory, and resource leaks — at build time, before a line of code executes on a customer’s machine. Visual Studio ships a fully integrated static analysis engine that requires no external tools: enable it with a single compiler flag, annotate your APIs with SAL macros, and optionally layer on the C++ Core Guidelines checker for modern C++ safety rules.

The /analyze Compiler Flag

The /analyze flag activates MSVC’s built-in code analysis engine. It runs as part of compilation and emits warnings to the same Error List window as ordinary compiler diagnostics.
cl /analyze /W4 /WX Sample.cpp
Add /analyze:log output.sarif to emit results in SARIF format for CI/CD consumption (Visual Studio 2022 and later).
Microsoft recommends enabling at least the Native Recommended rule set throughout your project’s entire development timeline — not just for release builds. The earlier a defect is caught, the cheaper it is to fix.

Common Warnings Caught by /analyze

The code analysis engine reports C6xxx and C28xxx warning codes. Some of the most impactful:
WarningCategoryDescription
C6001Uninitialized memoryUsing uninitialized memory
C6011Null dereferenceDereferencing a potentially NULL pointer
C6053Buffer overrunstrncpy / wcsncpy not null-terminated
C6200Index out of rangeArray index exceeds buffer size
C6386Buffer overrunWrite beyond buffer end
C6387Invalid parameterParameter could be 0 / NULL when not expected
C28182Null dereferencePointer is NULL in the same path as a dereference

SAL Annotations

SAL (Source Annotation Language) is a set of macros that describe the preconditions and postconditions of function parameters and return values. The code analysis engine uses these annotations to find more bugs, more accurately, with fewer false positives.

Core SAL Macros

#include <sal.h>

// _In_     — caller-supplied read-only input
// _Out_    — caller-allocated buffer written by callee
// _Inout_  — read and written by callee
// _In_z_   — null-terminated input string
// _Out_writes_(n) — buffer of n elements written by callee
// _Outptr_ — callee allocates and returns via pointer-to-pointer

// Example: safe string copy helper
errno_t SafeCopy(
    _Out_writes_z_(destSize) char* dest,
    _In_                     size_t destSize,
    _In_z_                   const char* src
);

Annotating a Real Function

// Without SAL: analyzer can't reason about buffer sizes
void FillBuffer(char* buf, int count);

// With SAL: analyzer knows buf has count writable bytes
void FillBuffer(
    _Out_writes_(count) char* buf,
    _In_                int   count
);

// Caller site — analyzer detects the mismatch:
char small[4];
FillBuffer(small, 10);  // C6386: buffer overrun!
Annotate your own APIs with SAL even if you don’t immediately enable /analyze. The annotations serve as machine-checked documentation and become valuable as the codebase grows or changes hands.

Null-Pointer Annotations

// _In_opt_  — parameter may be NULL; callee must check
// _Ret_maybenull_ — return value may be NULL; caller must check

_Ret_maybenull_
char* FindToken(_In_z_ const char* input, _In_ char delim);

void Process(_In_opt_ const Config* cfg) {
    if (cfg == nullptr) return;  // required guard
    // ...
}

Annotation Quick Reference

AnnotationMeaning
_In_Read-only parameter, must not be NULL
_In_opt_Read-only parameter, may be NULL
_In_z_Null-terminated string input
_Out_Output parameter, caller-allocated
_Out_opt_Optional output, may be NULL
_Inout_Read and modified by the function
_Out_writes_(n)Writable buffer of n elements
_In_reads_(n)Readable buffer of n elements
_Ret_maybenull_Return value may be NULL
_Ret_notnull_Return value is guaranteed non-NULL
_Outptr_Callee allocates; output via pointer-to-pointer

C++ Core Guidelines Checker

The C++ Core Guidelines Checker is an extension of the /analyze engine that enforces the C++ Core Guidelines authored by Bjarne Stroustrup and Herb Sutter. It is installed by default in Visual Studio 2017 and later.

Enabling the Core Check Rules

1

Open Project Properties

Right-click your project in Solution ExplorerProperties.
2

Navigate to Code Analysis

Go to Configuration PropertiesCode AnalysisMicrosoft.
3

Select rule sets

From the Active Rules dropdown, choose Choose multiple rule sets. In the dialog, add one or more of:
  • C++ Core Check Bounds Rules
  • C++ Core Check Type Rules
  • C++ Core Check Lifetime Rules
  • C++ Core Check Guidelines (full set)
4

Build and review

Build your project. Core Check warnings appear in the Error List with codes in the C26xxx range.

Example: Core Check Warnings

// CoreCheckExample.cpp — compile with /analyze

int main() {
    int arr[10];           // C26494: Type.5 — always initialize objects
    int* p = arr;          // C26485: Bounds.3 — no array-to-pointer decay

    // Use [[gsl::suppress]] to suppress specific rule violations with justification
    [[gsl::suppress("bounds.1", justification: "Reviewed: index is in range")]]
    {
        int* q = p + 1;    // C26481 suppressed — Bounds.1: use span instead
        p = q++;           // C26481 suppressed
    }

    return 0;
}
Key C++ Core Check warning codes:
CodeRuleDescription
C26400I.11Do not assign result of new to raw pointer
C26401I.11Do not delete a raw pointer not owned by this scope
C26409R.11Avoid explicit new / delete; use make_unique
C26429F.23Use not_null<T> to indicate when NULL is never valid
C26481Bounds.1Use span instead of pointer arithmetic
C26485Bounds.3No array-to-pointer decay
C26494Type.5Always initialize variables

Suppressing Warnings

Use #pragma warning to suppress specific analysis warnings on a per-file or per-line basis:
// Suppress a single warning for one line
#pragma warning(suppress: 6011)
char c = *pMaybeNull;  // C6011 suppressed — we verified above

// Disable a warning for a region
#pragma warning(push)
#pragma warning(disable: 6386)
legacy_api_with_no_sal(buf, 100);
#pragma warning(pop)

// Treat a specific warning as an error
#pragma warning(error: 6001)
Suppressing warnings should be a last resort. Prefer fixing the underlying issue or adding SAL annotations. When you must suppress, always include a comment explaining why the suppression is safe.

Configuring Analysis with .editorconfig

Visual Studio respects .editorconfig for per-directory linting configuration. While most static analysis settings live in project properties, you can use .editorconfig to enforce style-level rules that complement the analyzer:
# .editorconfig — place at solution or project root
root = true

[*.cpp]
# Warn on use of deprecated CRT functions
cpp_unsafe_buffer_usage = warning

# Require consistent include guards or #pragma once
indent_style = space
indent_size = 4
For code analysis rule sets, use a .ruleset file in your project and reference it from the Active Rules project property:
<!-- MyProject.ruleset -->
<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="My Custom Rules" ToolsVersion="17.0">
  <Include Path="nativerecommended.ruleset" Action="Default" />
  <Rules AnalyzerId="Microsoft.Analyzers.NativeCodeAnalysis" RuleNamespace="Microsoft.Rules.Native">
    <Rule Id="C6001" Action="Error" />
    <Rule Id="C6011" Action="Error" />
    <Rule Id="C26409" Action="Warning" />
  </Rules>
</RuleSet>

Integrating Analysis in CI/CD

Run /analyze in your CI pipeline to catch regressions before they merge:
# Azure Pipelines / GitHub Actions step
cl /analyze /analyze:log results.sarif /WX mylib.cpp
Upload the SARIF file to GitHub Advanced Security or Azure DevOps to see inline annotations on pull requests. You can also combine with BinSkim for binary-level checks after compilation:
binskim analyze mylib.exe --config default --output report.sarif

/analyze Reference

Full compiler flag documentation for code analysis options and rule set configuration.

SAL Annotations Guide

Complete SAL macro reference with examples for annotating structs, locking behaviors, and return values.

C++ Core Guidelines

The upstream guidelines document maintained by the Standard C++ Foundation at isocpp.github.io.

BinSkim User Guide

Binary-level security checker that validates PE/ELF hardening flags in compiled outputs.

Build docs developers (and LLMs) love