7

我有一个导致整数溢出的错误,导致错误(负)时间戳被写入数据库。代码已经修复了,但我也想修复错误的数据

我想,我可以只取错误的结果并添加 Integer.MAX_VALUE,但这似乎不起作用,它给我留下了很高的价值。我offset在下面的代码片段中有值,但没有存储输入值。

以下代码重现了该错误:

@Test
public void testArexxConversion()
{
    // The input values represent seconds since midnight, Jan 1, 2000 UTC
    final int sample = 361450072; // A sample input value drawn from production
    // I use the offset from the UNIX epoch to convert the vakue to UNIX seconds
    final int offset = 946684800; // midnight, Jan 01 2000 UTC in UNIX seconds
    // This was the buggy line in my code, the assertion will fail
    long result = (sample + offset) * 1000;
    // Prints 'Result is negative: -1830153280'
    Assert.assertTrue(result > 0, String.format("Result is negative: %d", result));
    // This is for comparison
    Date dt = new Date(offset * 1000);
    Assert.assertEquals(dt.getTime() + sample * 1000, result);
}
4

3 回答 3

5

如何修复数据库中的错误

要修复数据库中的错误,您可以对所有错误数据执行以下操作:

long new_result = old_buggy_result + 1309965025280L;

常数是这样找到的:

  1. 检查错误result
  2. 找出正确的result值应该是多少?
  3. 对错误result值进行添加以找到正确的`结果。

但这只有在您已保存sample并保存offset在数据库或其他地方时才有可能。

否则,它取决于原始计算期间发生的换行次数:

long size_of_int = (long)Math.pow(2, 32);
int number_of_wraps = 305 // Only correct in your example!
                          // You can't deduct the number of wraps from
                          // the wrong value alone, because that information
                          // is lost in the modulo (the "wrap")
long correct_number = wrong_number + size_of_int * number_of_wraps;

如果您的数据库中的数字与您的样本值足够接近,这意味着您可以执行上述操作,使用 305 作为换行次数。

错误说明(供未来读者使用)

这里的操作:

 (sample + offset) * 1000;

使用intand not计算long。但结果是“太大”而无法保存在int变量上。这就是为什么你有溢出。

将其更改为:

  ((long) sample + offset) * 1000L;

所以现在+and*操作将使用long值完成,结果将是一个long不会溢出的值。

于 2011-06-15T11:19:38.820 回答
2

那将是这样的:

long result = ... ; // bad negative from database
long new_result = (long)((int)result - Integer.MAX_VALUE) + Integer.MAX_VALUE;
于 2011-06-15T11:50:28.600 回答
0

替换此行。

long result = (long)(sample + offset) * 1000L;
于 2011-06-15T11:21:03.070 回答