Fact-checked by Grok 2 weeks ago

Off-by-one error

An off-by-one error (OBOE), also known as an off-by-one bug, is a prevalent in where a calculated or used numerical value deviates from the intended result by exactly one unit, often leading to incorrect program behavior such as incomplete processing or unintended memory access. This error typically arises from misjudging boundaries in iterative structures like loops or when handling zero-based versus one-based indexing in arrays and collections. It is classified as a in software assurance taxonomies due to its potential to cause subtle yet pervasive issues across various programming languages. Off-by-one errors commonly occur in loop constructs, where the iteration condition fails to account for inclusive or exclusive bounds, resulting in the loop executing one time too many or too few. For instance, in a for loop intended to process an array of length n using zero-based indexing, a condition like for (i = 0; i <= n; i++) will attempt to access index n, which is out of bounds and may cause a runtime exception or undefined behavior. Similarly, in recursive functions or while loops, incorrect termination conditions—such as using < instead of <=—can halt execution prematurely, skipping the final iteration. These mistakes are exacerbated in languages without built-in bounds checking, like C or C++, where the error may silently corrupt memory rather than immediately failing. The consequences of off-by-one errors range from minor logical discrepancies to severe security vulnerabilities, including buffer overflows that enable arbitrary code execution or data leaks. In one documented case from program analysis studies, an off-by-one error in a string replacement function assigned results using i + 1 instead of i, leading to mismatched outputs in pattern matching. Such errors occur in real-world codebases, as identified in empirical studies of open-source projects. To mitigate them, developers are advised to manually trace loop executions, employ half-open intervals (e.g., iterating from 0 to n exclusive), and incorporate boundary-testing in unit tests. Automated static analysis tools can also detect many instances with high effectiveness, though human review remains essential for boundary logic.

Fundamentals

Definition

An off-by-one error is a logic error in programming wherein a calculated or used value, such as a boundary condition in an iterative process like a loop or count, is exactly one unit more or one less than the intended value, resulting in the processing of one more or one fewer elements than required. This discrepancy often stems from incorrect handling of boundary conditions, leading to subtle but pervasive issues in program execution. Key characteristics of off-by-one errors include mismatches between zero-based indexing (common in many programming languages, where the first element is at index 0) and one-based indexing (where the first element is at index 1), confusion over whether bounds are inclusive or exclusive, and errors in computing lengths or sizes of data structures. For instance, these errors frequently manifest in loops that traverse or sequences, where the iteration limit is mis-set by one. Mathematically, consider an array of size n; the valid indices range from 0 to n-1, so a correct loop iterates as \text{for } i = 0 \text{ to } n-1. An off-by-one error might instead use \text{for } i = 0 \text{ to } n, attempting access to the invalid index n, which can cause undefined behavior or crashes. Unlike general indexing errors or overflows with arbitrary displacements, an off-by-one error is distinctly characterized by a precise offset of exactly one unit, making it a specific subtype of boundary-related logic flaws. This concept draws an analogy to the fencepost error in everyday counting, where the number of fence posts needed is one more than the number of panels to enclose a space.

Historical Context

Off-by-one errors trace their roots to the earliest high-level programming languages of the 1960s, where documentation highlighted challenges with indexing and loop boundaries that could lead to such discrepancies. In the 1961 COBOL General Information Manual, subscripts for table access were required to be positive integers, with restrictions against nesting or use in certain clauses to prevent access issues, while the PERFORM UNTIL statement explicitly described loop termination as excluding the final value— for instance, varying a factor from -1.00 by 0.05 until 0.50 would process up to 0.45 but omit 0.50, a behavior prone to miscalculation by programmers expecting inclusive endpoints. Similarly, early FORTRAN systems manuals from the late 1950s and early 1960s, such as the 1960 Systems Manual for 704 and 709 FORTRAN, addressed diagnostic programs for source errors during compilation, including those related to array indexing in scientific computations, though specific off-by-one terminology was absent. By the 1970s, off-by-one errors were increasingly noted in systems documentation as frequent issues for novice programmers, particularly in mainframe environments. IBM's FORTRAN implementations for System/360, documented in user guides from the era, emphasized common logical errors in loop constructs and array operations, where index misalignments often arose due to varying compiler diagnostics for boundary violations. These reports underscored the persistence of such errors despite advances in language design, as debugging tools focused on syntax rather than runtime bounds checking. The evolution of off-by-one errors continued into modern languages, exemplified by C's introduction in 1972, which standardized zero-based indexing to align with hardware efficiency but introduced new pitfalls. In The C Programming Language (first edition, 1978), Kernighan and Ritchie noted that "array subscripts always start at zero," warning that accessing outside bounds yields undefined behavior, and provided examples like loop conditions such as i < lim-1 in getline to prevent overflow by one element. They highlighted common mistakes, such as in pointer arithmetic where a[i] = i++ could use the old or new value of i depending on compiler order, risking off-by-one shifts. Despite these standards, the error persisted across languages due to human tendencies in handling discrete boundaries. The term "off-by-one error" gained cultural traction in the 1980s through hacker communities and Usenet discussions, embedded in folklore as a quintessential programming blunder. The 1983 edition of The Hacker's Dictionary (derived from the , originating at in the 1970s) defined it as "the discrete equivalent of a boundary condition," often illustrated by fencepost analogies like miscalculating posts for a 100-foot fence spaced 10 feet apart (requiring 11 posts, not 10). By the 1990s, it received formal classification in software engineering texts and standards; for example, the for Software Anomaly Classification included logic errors like boundary miscalculations under defect types, enabling systematic tracking in development processes.

Common Scenarios

Array and Index Operations

Off-by-one errors frequently arise in array and index operations due to the prevalence of zero-based indexing in many programming languages, where the first element is accessed at index 0 and the last at index n-1 for an array of length n. This convention, inherited from low-level memory addressing, contrasts with one-based indexing common in mathematical notation or certain domain-specific languages like , where indices start at 1. Programmers accustomed to one-based systems may inadvertently use indices from 1 to n, resulting in skipped elements or buffer overruns when accessing beyond the array's bounds. A common manifestation involves miscalculating array length during access or iteration. The length function, such as Python's len(array), returns the total number of elements n, but valid indices range only from 0 to n-1. For instance, attempting to access array[n] invokes undefined behavior in languages without bounds checking or throws an exception in others, while using index 1 to n-1 skips the first element. This error often stems from conflating the array's size with its maximum index, leading to partial data processing or memory corruption. To illustrate, consider pseudocode for summing elements in an array of length n. An erroneous version might use a condition that includes the upper bound incorrectly:
sum = 0
for i = 0 to n  // Error: i reaches n, accessing array[n] which is out of bounds
    sum += array[i]
This accesses one element too many, potentially causing a . The correct implementation uses a strict less-than condition:
sum = 0
for i = 0 to n-1  // Or equivalently, i < n
    sum += array[i]
In the faulty code, if n=5, i iterates from 0 to 5, attempting to read array which does not exist. The proper loop processes indices 0 through 4, ensuring all elements are summed without overflow. Such walk-throughs highlight how a single inequality mismatch (≤ vs. <) shifts the boundary by one. Language-specific features exacerbate these risks. In C, arrays lack built-in bounds checking, so accessing an invalid index like array results in undefined behavior, often leading to segmentation faults or security vulnerabilities like . Python, while also zero-based, provides dynamic lists but raises an for out-of-range access, aiding detection though not prevention. Java throws an for illegal indices (negative or ≥ length), explicitly signaling the error but requiring explicit handling to avoid runtime crashes. These differences underscore the need for careful index validation tailored to the language's memory model.

Loop Constructs

Off-by-one errors in loop constructs frequently arise from misconfigured boundaries or iteration controls, causing loops to execute one more or one fewer time than intended. These errors are prevalent in programming because loops rely on precise counting to process data correctly, and small discrepancies in conditions or increments can lead to significant deviations in output or behavior. For instance, developers often overlook whether a loop should include or exclude boundary values, resulting in unintended over- or under-iteration. In for-loops, a common pitfall involves inclusive upper bound errors, where the condition uses <= instead of <, leading to one extra iteration. Consider a loop intended to iterate over indices 0 through n-1 in an array of length n; using for (int i = 0; i <= n; i++) accesses an out-of-bounds index n, potentially causing runtime errors or incorrect results. The correct form, for (int i = 0; i < n; i++), ensures exactly n iterations. This issue stems from confusion over whether the upper bound should be inclusive, and it is a frequent source of bugs in languages like and . While and do-while loops introduce off-by-one errors through imprecise condition checks or mismatched increments, often resulting in loops that terminate prematurely or continue indefinitely. In a while loop accumulating values until a sentinel, failing to "prime" the input by reading before the loop can include the sentinel in the count, inflating the iteration tally by one; for example, a loop processing positive integers until 0 might erroneously count the terminating 0, yielding an off-by-one in the average calculation. Do-while loops, which check conditions post-execution, exacerbate this if the body increments incorrectly relative to the test, such as using intCount < 5 instead of <= 5 in a summation loop from 1 to 5, excluding the final value and undercounting by one. These errors highlight the need for careful alignment between update statements and termination logic. Range-based loops in languages like Python are susceptible to off-by-one errors due to the exclusive upper bound of the range() function, which generates sequences from start to stop-1. For example, for i in range(n) iterates n times from 0 to n-1, but using range(n+1) to include n would over-iterate by one, potentially processing extraneous data. This behavior, while efficient for zero-based indexing, trips up programmers expecting inclusive ranges, especially when interfacing with one-based systems or miscalculating sequence lengths. Iteration count errors occur when formulas for determining loop repetitions are misapplied, such as incorrectly adjusting for zero-based starts in expressions like total_steps = end - start + 1, leading to an extra step if start is overlooked as zero. In practice, this manifests in loops where the computed count assumes inclusive bounds but the actual condition excludes them, causing under-iteration; for instance, setting a loop to run end - start times instead of end - start + 1 skips the final iteration. Defensive programming techniques, like verifying termination conditions against test cases, help mitigate these discrepancies in loop planning.

Fencepost Error

The fencepost error is a specific manifestation of the off-by-one error, arising from a failure to distinguish between the count of dividing elements (such as posts) and the count of intervals or connections between them (such as rails). The analogy originates from the practical task of building a fence: to enclose n segments of railing, one requires n+1 posts, as each post serves as a boundary for the adjacent segments. Conversely, with m posts, the number of rail segments that can be supported is m-1. Mistaking the posts for the rails—or vice versa—results in procuring one too few or one too many components, exemplifying how intuitive counting can lead to systematic discrepancies in discrete resource allocation. The analogy was adapted to computing contexts in the 1970s and 1980s within hacker and academic communities, appearing in glossaries and educational materials to describe indexing and boundary issues in algorithms. For instance, Donald Knuth's The Art of Computer Programming (first volumes published 1968–1973) discusses related off-by-one pitfalls in array indexing and loop controls, laying groundwork for recognizing such errors in program design, though the explicit "fencepost" terminology gained traction later in computer science literature. At its core, the fencepost error rests on a mathematical foundation that generalizes to discrete partitioning problems. In such scenarios, the resources needed for boundaries follow the relation resources_needed = segments + 1 when dividers enclose intervals (e.g., posts for rails), or resources_needed = segments - 1 when connectors link fixed points (e.g., rails for posts). This formula ensures proper delineation in linear or array-like structures, preventing overflow or undercounting. In programming, the fencepost analogy maps directly to data partitioning tasks, where conceptual boundaries must separate elements without overlap or omission. For example, dividing n items into k non-empty groups necessitates k+1 boundaries to define the transitions between groups, as each boundary marks the start or end of a segment. Overlooking this extra boundary can result in misallocated memory or incorrect slicing, underscoring the error's prevalence in algorithmic design where counts of delimiters differ from counts of contents. A concrete example occurs when initializing an array to store k dividers for n elements; using size k instead of k+1 leads to buffer overflow. For instance, in C, declaring int dividers[k]; for k groups omits the final boundary, causing out-of-bounds access.

Consequences

Debugging Challenges

Off-by-one errors often manifest as intermittent failures that are challenging to reproduce, such as skipping the last element in an array or crashing on seemingly valid input near boundaries, due to their sensitivity to specific data sizes or edge cases. These symptoms arise from incorrect boundary conditions, like using < instead of <=, leading to out-of-bounds access or incomplete processing that only appears under particular conditions. Diagnostic techniques for identifying off-by-one errors typically involve inserting print statements to log index values at loop boundaries and using assertions to validate ranges, such as assert(i >= 0 && i < n);, which halts execution if bounds are violated. These methods help trace discrepancies in iterative code by providing visibility into states without relying on complex tools. Off-by-one errors contribute significantly to debugging time, as they are prevalent in boundary-sensitive code; empirical studies of real-world projects identified 41 such bugs across top repositories, highlighting their persistence despite scrutiny. General metrics from the 2000s report that defect rework, including logic errors like off-by-one in iterative constructs, can consume 40-50% of total development costs, underscoring the resource intensity of resolution. Cognitive biases exacerbate debugging difficulties with off-by-one errors, as programmers often overlook "obvious" bounds due to , testing only expected paths and ignoring contradictory evidence that could reveal the off-by-one issue. This tendency leads to prolonged confirmation of incorrect assumptions during testing, delaying identification in subtle cases.

Security Vulnerabilities

Off-by-one errors in array indexing or string handling can create exploitable vulnerabilities by allowing attackers to access or overwrite memory beyond intended boundaries, often leading to buffer overflows that enable code execution or denial-of-service attacks. In languages like C and C++, where manual memory management is common, an off-by-one mistake—such as failing to account for the null terminator in string operations—can result in functions like strcpy copying one byte too many, overwriting adjacent stack memory and facilitating stack-smashing attacks. This pattern exploits the lack of automatic bounds checking, turning a simple indexing error into a gateway for arbitrary code injection. Such errors have been involved in notable vulnerabilities; for example, CVE-2021-3156 (known as Baron Samedit) in the utility stemmed from an off-by-one error in command-line argument parsing, leading to a heap-based that allowed unprivileged users to gain root access on systems. The prevalence of off-by-one flaws is evident in the Common Weaknesses Enumeration (CWE-193), which maps to numerous CVEs with high severity scores (CVSS 7.0 or above) due to their potential for remote exploitation and system compromise. To address these patterns in secure coding, organizations like CERT recommend explicit bounds checking in string and array manipulations—such as validating input lengths before copying—to prevent overflows, emphasizing vulnerability-specific defenses like input in C-family languages without relying on runtime protections alone.

Prevention Strategies

Coding Techniques

One effective coding technique to mitigate off-by-one errors involves adopting consistent inclusive/exclusive boundary conventions, particularly for and operations. Programmers should standardize on half-open intervals, where the lower bound is inclusive and the upper bound is exclusive, such as iterating from 0 to less than the (e.g., for (size_t i = 0; i < array_size; i++)). This approach aligns with the natural properties of zero-based indexing in most programming languages and simplifies calculations, as the size of a [start, end) is simply end - start, reducing the cognitive load and error risk during implementation. Documenting these zero-based assumptions explicitly in code comments, such as noting "Array indices are 0-based; upper bound is exclusive," further reinforces the convention and aids by clarifying intent for other developers. Defensive programming patterns also play a crucial role in preventing off-by-one errors by emphasizing explicit initialization and avoidance of ambiguous values. Indices and counters should be initialized to known safe values before use, such as setting size_t i = 0; at the start of a , to avoid relying on uninitialized or default behaviors that could lead to miscalculations. Replacing with named constants, like defining const size_t ARRAY_SIZE = 10;, ensures that bounds are clearly defined and easily adjustable, minimizing errors from hardcoded literals that might inadvertently include or exclude an element. Additionally, incorporating runtime assertions or checks, such as assert(index < ARRAY_SIZE);, provides immediate feedback during if boundaries are violated, though these should be disabled in production for . To institutionalize these practices, teams should employ structured review checklists during peer code inspections, focusing on off-by-one prone elements. Key items include verifying loop invariants (e.g., ensuring the condition maintains i < length throughout iterations), testing edge cases like empty arrays (length = 0), single-element arrays (length = 1), and full arrays (length = maximum), and confirming that all array accesses respect declared sizes without overflow. Such checklists promote a systematic approach, catching subtle boundary issues that might otherwise propagate to runtime failures or security vulnerabilities like buffer overflows. Language-agnostic tips extend these principles beyond low-level languages, prioritizing abstractions that abstract away manual indexing. For instance, favoring higher-level constructs like foreach loops or iterator-based traversals (e.g., in Python's for item in collection: or Java's enhanced for-loop) eliminates the need to manage indices directly, inherently avoiding off-by-one errors in iteration logic. When manual indexing is unavoidable, always prefer unsigned types like size_t for counters to prevent signed/unsigned mismatches that exacerbate boundary errors, and consistently validate inputs against expected ranges before processing. These habits foster robust code across paradigms while motivating vigilance against consequences like unintended .

Tools and Verification Methods

Static analysis tools play a crucial role in identifying off-by-one errors by examining code without execution, focusing on potential bounds violations in arrays, loops, and memory accesses. , a commercial (SAST) tool, excels at detecting buffer overflows and related defects that often stem from off-by-one mistakes in C and C++ codebases, analyzing complex control flows to flag issues like array index overruns. For JavaScript development, serves as a pluggable linter that can be extended with plugins and custom rules to enforce code quality and catch potential logic errors, though it is not specifically designed for static detection of off-by-one violations in dynamic array accesses. At runtime, tools like Valgrind's Memcheck detect memory errors including invalid reads and writes caused by off-by-one errors, such as accessing one element beyond an array's boundary, by instrumenting programs to track memory usage and report out-of-bounds accesses in C and C++ applications. Unit testing frameworks facilitate the prevention of off-by-one errors through systematic (BVA), a technique that targets input edges to expose defects like index miscalculations. In , enables developers to write targeted test cases that verify behavior at critical points, such as array indices i = -1, 0, n-1, and n, ensuring loops and accesses handle boundaries correctly and catching off-by-one issues early in the development cycle. This approach prioritizes testing equivalence partitions' edges, where errors are most likely, over exhaustive coverage of all values. Formal verification methods provide mathematical proofs of correctness, eliminating off-by-one errors by specifying and checking properties like loop invariants. , a verification-aware programming language, allows developers to annotate loops with invariants—assertions that remain true across iterations—proving that indices stay within bounds and preventing overflows or underflows in array operations. For instance, invariants can establish that a loop counter i satisfies 0 ≤ i < n throughout execution, enabling Dafny's verifier to confirm the absence of off-by-one errors without runtime testing. Integrated development environment (IDE) features enhance detection during coding and . Modern IDEs like offer built-in debuggers with watchpoints, which monitor changes to specific variables such as array indices, halting execution when an off-by-one condition alters the value unexpectedly and aiding in real-time error isolation. Additionally, VS Code extensions for linters provide inline warnings for potential code issues directly in the editor, streamlining without leaving the workflow.

References

  1. [1]
    CWE-193: Off-by-one Error
    For example, an off-by-one error could be a factor in a partial comparison, a read from the wrong memory location, an incorrect conditional, etc. + Taxonomy ...Missing: credible | Show results with:credible
  2. [2]
    Off-by-One Error | Baeldung on Computer Science
    Jun 10, 2023 · An off-by-one error is a logical error related to start/end values of a memory range, occurring when exceeding or missing a boundary by one.
  3. [3]
    CSE 101: Computer Science Principles
    ... 1. Off-by-one errors. Sometimes a while loop or recursive function might stop one iteration too short. Here, it's best to walk through the iteration/recursion ...
  4. [4]
    [PDF] Mining Control Flow Abnormality for Logic Error Isolation∗
    In Pro- gram 2, the programmer mistakenly assigns the variable result with i+1 instead of i, which is a typical “off- by-one” logic error. The error in Program ...
  5. [5]
    [PDF] Systems Reference Library - Bitsavers.org
    The COBOL language described in this manual consists of all of REQUIRED COBOL-. 1961 as so defined, together with a large portion of ELECTIVE COBOL- ...
  6. [6]
    [PDF] Systems Manual for 704 and 709 Fortran - Bitsavers.org
    A diagnostic program exists for source program errors found or machine errors occurring during Section One. The program consists of: Program ...
  7. [7]
    [PDF] IBM 1130 Computing System User's Guide
    Jan 13, 1970 · This manual, covering a wide range of subjects that are of interest to 1130 customer personnel, is designed for insertion in a workbook.
  8. [8]
    None
    Below is a merged summary of array indexing, common pitfalls, and off-by-one errors in *The C Programming Language* by Kernighan and Ritchie, consolidating all information from the provided segments into a dense, organized format. To maximize detail retention, I’ll use a combination of narrative text and a table in CSV format for key points, ensuring all relevant sections, quotes, examples, and observations are included.
  9. [9]
    The Original Jargon File (Year 1983) (The Hacker's Dictionary)
    Feb 24, 2023 · An "off-by-one" error: the discrete equivalent of a boundary condition. ... (In everyday terms, this means that it's a lot easier to clean off ...
  10. [10]
  11. [11]
    5. Data Structures — Python 3.14.0 documentation
    List comprehensions provide a concise way to create lists. Common applications are to make new lists where each element is the result of some operations.
  12. [12]
    [PDF] CSE 331 Spring 2025 - Washington
    • Most likely bug is an off-by-one error. – must check S[j], not S[j-1] or S[j+1] j. S. __ ≠ y j+1 j. S. __ ≠ y. 49. Page 43. Array Indexing & Off-By-One Bugs ...
  13. [13]
  14. [14]
    ArrayIndexOutOfBoundsException (Java Platform SE 8 )
    ArrayIndexOutOfBoundsException is thrown when an array is accessed with an illegal index, which is either negative or greater than or equal to the array's size.
  15. [15]
    Off-By-One Error
    Off-By-One Error. Off-by-one error occurs when we have "<=" instead of "<" when we are checking the expression in the loop.
  16. [16]
    off by one error | Amazon Q, Detector Library - AWS Documentation
    Off-by-one errors are programming mistakes where loops or array indices are improperly incremented or decremented by one, resulting in unintended behavior.Missing: definition sources
  17. [17]
    Javanotes 8.1.3, Section 3.4 -- The for Statement
    Using < instead of <= in the test, or vice versa, is a common source of off-by-one errors in programs. You should always stop and think, Do I want the final ...
  18. [18]
    Javanotes 9, Section 3.3 -- The while and do..while Statements
    Such so-called off-by-one errors are very common. Counting turns out to be harder than it looks!) We can easily turn the algorithm into a complete program.
  19. [19]
    Intro to Repetition Structures - UC Homepages
    When considering pre-test loops, the standard example is the Do-While loop. ... This error is another example of a nasty "off by 1" error. Using only the ...
  20. [20]
    4. More Control Flow Tools
    ### Summary of `for` Loops with `range()` and Related Common Errors/Off-by-One Issues
  21. [21]
    [PDF] Defensive Programming II - Loops
    Defensive Programming. II ... result from a sequence of repeated actions. - such as in games and loops. 18. Page 19. Common Bugs in. Loops: Off-by-1 error.
  22. [22]
    [PDF] Learning Off-By-One Mistakes: An Empirical Study
    In order to detect off-by-one errors in Java code, we aim to create a hypothesis function that will calculate output based on the inputs generated from an ...
  23. [23]
    Use C++ assertion statements for debugging - Visual Studio ...
    Apr 18, 2024 · You can use assertions to catch logic errors, check results of an operation, and Test error conditions that should have been handled.
  24. [24]
    Asserting Expectations - The Debugging Book
    Assertions are a tool to define assumptions on function inputs and results, checking conditions at runtime, and failing if the condition is false.
  25. [25]
    Debugging Facts and Statistics
    Jul 11, 2011 · Reworking defects in requirements, design, and code consumes 40-50% of the total cost of software development. · Every hour spent on defect ...Missing: errors 2000s
  26. [26]
    [PDF] A Tale from the Trenches: Cognitive Biases and Software ...
    ABSTRACT. Cognitive biases are hard-wired behaviors that influence developer actions and can set them on an incorrect course of action, necessi-.
  27. [27]
    Cognitive Biases in Software Development
    Apr 1, 2022 · Cognitive biases are hardwired behaviors that influence developer actions and can set them on an incorrect course of action, necessitating backtracking.
  28. [28]
  29. [29]
    [PDF] using static analysis to find bugs in the real world - Columbia CS
    In 2002, COVErITY commercialized3 a research static bug-finding tool.6 ... a static analyzer for finding dynamic programming errors. Software: Practice ...
  30. [30]
    Configure Rules - ESLint - Pluggable JavaScript Linter
    A pluggable and configurable linter tool for identifying and reporting on patterns in JavaScript. Maintain your code quality with ease.
  31. [31]
    4. Memcheck: a memory error detector - Valgrind
    Memcheck is a memory error detector. It can detect the following problems that are common in C and C++ programs. Incorrect freeing of heap memory.Missing: runtime | Show results with:runtime
  32. [32]
    Boundary Value Analysis in Software Testing - C# Corner
    Boundary value analysis is a software testing design technique to determine test cases covering off-by-one errors.
  33. [33]
    Dafny Documentation
    ... verification tools require loop invariants, which are another kind of annotation. A loop invariant is an expression that holds just prior to the loop test ...
  34. [34]
    [PDF] Getting Started with Dafny: A Guide - Microsoft
    Dafny is also able to use the loop invariants to prove that after the loop, i == n and b == fib(i), which together imply the postcondi- tion, b == fib(n).
  35. [35]
    Linting Python in Visual Studio Code
    Errors and warnings are shown in the Problems panel (Ctrl+Shift+M) ; Logs for linters are available in the Output panel (Ctrl+K Ctrl+H) ; You can change the log ...