增量工作很奇怪

Increment working very strangely

本文关键字:工作      更新时间:2023-10-16

程序应该给出任意大小的后100位的阶乘。然而,main()中的counter++发生了一些奇怪的事情。每次循环在main()函数中运行一次,Counter2就加1(即99次)。但是显示的内容是:

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
71
86
90
123
164
196
207
254
300
362
432
471
551
620
630
708
761
772
857
896
985
1036
1100
1116
1207
1209
1280
1356
1417
1452
1512

Counter2最终是1512而不是100,但如果我从main()中删除mult(I)或carry(),则它显示100。为什么counter2最后是1512而不是100?

#include <iostream>
using namespace std;
int numbers[100];
int counter2 = 0;
void init(){
//sets elements 1-99 of numbers[] to 0, increments counter2 by 1, sets numbers[0] = 1
    for (int i = 1; i < 100; i++){
        numbers[i] = 0;
    }
    numbers[0] = 1;
    counter2++;
}
void mult(int x){
//multiplies each element by 1 through n to calculate for !n
//this is used to represent a very large number without using a BigInt library
//the nth element is a placeholder for the n+1 position of the number
//e.g 2nd element represents 100-900 of the number, 4th represents 1000-9000, etc
//carry() is used to take care of overflow, so that it's only 1 digit per element
    for (int i = 0; i < 100; i++){
        numbers[i] *= x;
    }
}
void carry(){
//in order to make previous function work, this adds any overflow to the next
//element. e.g: 8 * 4 = 32, 3 is added to numbers[i+1], sets numbers[i] to 2
    int counter = 0;
    for (int i = 0; i < 100; i++){
        if (numbers[i] >= 10){
            counter = numbers[i] / 10;
            numbers[i+1] += counter;
            numbers[i] = numbers[i] % (counter * 10);
        }
    }
}
int main()
{
    init();
    for (int i = 2; i < 101; i++){
    //calculates the last 100 digits of !100, but counter2 ends up being 1512
        mult(i);
        carry();
        counter2++;
        cout << counter2 << endl;
    }
}

您正在写入carry()numbers数组的末尾:

        numbers[i+1] += counter;

这里i可以是99,此时numbers[i+1]越界。

从技术上讲,这是未定义的行为。实际情况是,您覆盖了count2变量,该变量恰好位于数组后面的内存中。

关于内存漏洞的一个令人讨厌的事情是,它们可以在很长一段时间内没有症状,然后在最糟糕的情况下出现。valgrind是检测这类问题的一个很好的工具。

本行

 numbers[i+1] += counter;

i == 99改变int counter2 = 0;的值(在你的情况下,但不一定)正好在内存中的数字旁边时,你正在写数组numbers[100];