Off by one

"Off by one" 是一种常见的编程错误,通常指的是在程序中错误地访问了数组、循环或其他数据结构的边界。这个错误的名字源于计数通常是从1开始而不是从0开始的情况,导致程序在边界处出现偏差。下面将介绍如何避免它。

1.数组越界

"Off by one" 错误中最常见的形式是数组越界。在C++中,数组的索引是从0开始的,因此如果我们错误地使用了数组长度作为索引,就会导致数组越界。

#include <iostream>
int main() {
    int arr[5] = {1, 2, 3, 4, 5};

    // 错误:访问了数组越界
    for (int i = 0; i <= 5; ++i) {
        std::cout << arr[i] << " ";
    }
    return 0;
}

在这个例子中,循环条件中使用了 <=,导致在 i 变成5时访问了 arr[5],而数组的有效索引只有0到4。这种错误可能会导致程序崩溃或产生不可预测的结果。

2.循环条件错误

另一种"Off by one"错误发生在循环条件中。如果循环条件的边界设置不当,也可能导致多次或少次迭代。

#include <iostream>
int main() {
    // 错误:循环条件导致了多次迭代
    for (int i = 0; i < 5; ++i) {
        std::cout << i << " ";
    }
    return 0;
}

在这个例子中,循环条件应为 i < 5,但由于错误地设置成 i <= 5,导致循环多次迭代,输出了不必要的值。

3.字符串处理错误

"Off by one"错误也常见于字符串处理,特别是在C-style字符串(以null结尾的字符数组)中。

#include <iostream>
#include <cstring>
int main() {
    char str[5];
    strcpy(str, "Hello, World!");
    // 错误:字符串长度不够,未能包含null终止符
    for (int i = 0; i <= 5; ++i) {
        std::cout << str[i];
    }
    return 0;
}

    在这个例子中,字符数组 str 的长度为5,但字符串 "Hello, World!" 的长度超过了5,导致未能包含null终止符。这可能导致未定义的行为。

4.避免"Off by one"错误的方法

a.注意数组索引: 确保正确使用数组的索引,不要超出数组的边界。

    b.仔细设置循环条件: 在编写循环时,仔细检查循环条件,确保它不会导致多次或少次迭代。

    c.使用标准库函数: 在字符串处理时,尽量使用C++标准库中提供的字符串类和函数,如 std::string,以避免手动处理字符串时可能出现的"Off by one"错误。

    d.审查代码: 定期审查代码,特别关注循环、数组和字符串处理的部分,检查是否存在潜在的"Off by one"错误。

    5.off-by-one 利用思路 

1.溢出字节为可控制任意字节:通过修改大小造成块结构之间出现重叠,从而泄露其他块数据,或是覆盖其他块数据。也可使用 NULL 字节溢出的方法

2.溢出字节为 NULL 字节:在 size 为 0x100 的时候,溢出 NULL 字节可以使得 prev_in_use 位被清,这样前块会被认为是 free 块。

(1) 这时可以选择使用 unlink 方法(见 unlink 部分)进行处理。

(2) 另外,这时 prev_size 域就会启用,就可以伪造 prev_size ,从而造成块之间发生重叠。此方法的关键在于 unlink 的时候没有检查按照 prev_size 找到的块的大小与prev_size 是否一致。

全部评论
加油
点赞 回复 分享
发布于 2023-12-27 20:31 黑龙江

相关推荐

听说改名字就能收到offer哈:Radis写错了兄弟
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务