我有一个包含400个元素的整数数组。我用0初始化每个元素(甚至在之后检查它是否真的是0,因为我找不到这种行为的原因)。
然后,我选择10000个随机[1]索引,并将这些索引处的数组元素增加一。随机选择的指数中没有一个大于321(我确实检查了一下)。然而,在这10000个随机增加之后,索引为399或398的数组元素大于0。为什么?
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stddef.h>
#include <time.h>
#define NUM_INCREASES 10000
#define RESULTS_SIZE 400
#define ONES_IDX 2
#define TENS_IDX 1
#define HUNDREDS_IDX 0
int main(int argc, char * argv[]) {
int decimalDigits[3];
int results[RESULTS_SIZE] = {0};
srand(time(NULL));
for (int i=0; i<RESULTS_SIZE; i++) {
if (results[i]>0) {
printf("%05d %05d n", results[i], i);
}
}
puts("---");
for (int i=0; i<NUM_INCREASES; i++) {
decimalDigits[0] = 0;
decimalDigits[1] = 0;
decimalDigits[2] = 0;
for (int digitIncrease = 0; digitIncrease<3; digitIncrease++) {
int digitIndex = rand()%(decimalDigits[ONES_IDX]>0 ? 2 : 3);
if (digitIndex == TENS_IDX && decimalDigits[TENS_IDX] == 2) {
digitIndex -= 1 + 2*(i%2);
}
decimalDigits[digitIndex]++;
}
if (decimalDigits[TENS_IDX] > 2 || decimalDigits[ONES_IDX] > 1) {
fprintf(stderr, "error %dn", __LINE__);
}
int toIncrease = decimalDigits[HUNDREDS_IDX] * 100 + decimalDigits[TENS_IDX] * 10 + decimalDigits[ONES_IDX];
if (toIncrease < 0 || toIncrease > 321) {
fprintf(stderr, "error %dn", __LINE__);
}
results[toIncrease]++;
}
for (int i=0; i<RESULTS_SIZE; i++) {
if (results[i]>0) {
printf("%05d %05d n", results[i], i);
}
}
return EXIT_SUCCESS;
}
GCC和clang都会发生这种情况。我在三台不同的机器上看到过。valgrind和gdb都没有向我报告任何问题。
样本输出为
---
00183 00020
01763 00021
03618 00111
01263 00120
01738 00201
01068 00210
00367 00300
00183 00399
这里的错误是什么?399不应该在输出的第二列中。
脚注:
[1] 随机索引是从数字0开始生成的。然后将该数字的一个随机小数位数增加3倍。但是,"一"位数最多增加1次。"十"位数最多增加2倍。
当我按如下方式运行代码时,这一行会导致负数组索引:
for (int digitIncrease = 0; digitIncrease<3; digitIncrease++) {
int digitIndex = rand()%(decimalDigits[ONES_IDX]>0 ? 2 : 3);
if (digitIndex == TENS_IDX && decimalDigits[TENS_IDX] == 2) {
digitIndex -= 1 + 2*(i%2);
}
decimalDigits[digitIndex]++; //Negative array index here
}
我至少会开始查看那个块,也就是说,它不容易遵循,可能是你逻辑中的一个错误。
您正在访问decimalDigits
的越界元素。
在UB 之前尝试这3行
if (digitIndex < 0 || digitIndex >= 3) {
fprintf(stderr, "error %dn", __LINE__);
}
decimalDigits[digitIndex]++;