提问人:Ray Hamel 提问时间:4/27/2021 更新时间:4/27/2021 访问量:443
您如何发现或避免犯错?[关闭]
How do you spot or avoid committing off-by-one errors? [closed]
问:
当我编写代码时,我创建的更常见的错误类是差一错误 (OBO)。在“真实”代码中,我最常在用 C 或 C++ 进行复杂的指针/迭代器算术时遇到这个问题,但我有时在工作面试和家庭作业(例如实现合并排序)问题中也遇到问题,我使用其他编程语言。
我的典型调试策略包括随机交换 和 、 和 以及 附加 或 到变量,直到代码看起来正常工作。我很想知道有什么更好的策略或工具(例如静态分析、调试器/IDE 功能等)来发现 OBO。<
<=
++var
var++
+ 1
- 1
我对诸如“避免 C 样式循环”、“避免指针算术”、“函数式代码”或“使用不同的编程语言”之类的 pat 答案并不特别感兴趣。是的,这些事情可以缓解问题,但并不总是可以做到,而且它们并不能完全消除 OBO 危险。
例如,我相信以下代码,C(或者它也是有效的 C++)实现,没有 OBO。但正如你所看到的,OBO可能会出现数十个潜在的问题领域。有没有办法轻松确认它实际上没有 OBO?strcpy(3)
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#if !defined(__GNUC__) && !defined(__attribute__)
#define __attribute__(X)
#endif
#ifdef __cplusplus
extern "C" {
#if defined(__GNUC__) || defined(_MSC_VER) || defined(__restrict)
#define restrict __restrict
#elif !defined(restrict)
#define restrict
#endif
#endif
static inline bool aligned8(const void *ptr) {return !((uintptr_t)ptr & 7);}
static inline bool aligned4(const void *ptr) {return !((uintptr_t)ptr & 3);}
static inline bool aligned2(const void *ptr) {return !((uintptr_t)ptr & 1);}
/* Positive return value is the greatest common alignment (≤8) of the pointers.
* Negative return value is the byte offset that when added to both pointers
* yields a pair of pointers with alignment ≥8.
*/
static inline int common_alignment(const void *p1, const void *p2) {
if (aligned8(p1)) {
if (aligned8(p2))
return 8;
else if (aligned4(p2))
return 4;
else if (aligned2(p2))
return 2;
} else if (aligned4(p1)) {
if (aligned8(p2))
return 4;
else if (aligned4(p2))
return -4;
else if (aligned2(p2))
return 2;
} else if (aligned2(p1)) {
if (aligned4(p2))
return 2;
else if (aligned2(p2))
return -6;
} else if (!aligned2(p2)) {
return -7;
}
return 1;
}
/* strcpy implementation
*/
__attribute__((nonnull))
size_t string_copy(char *restrict dst, const char *restrict src) {
size_t i = 0;
int align = common_alignment(dst, src);
if (align < 0) {
for (; i < (size_t)-align; ++i)
if (!(*dst++ = *src++))
return i;
align = 8;
}
const size_t mask = (size_t)align - 1;
#define ALIGNED_STRING_COPY_IMPL_(BITS) do {\
uint##BITS##_t *restrict dst##BITS = (uint##BITS##_t*)dst;\
while (*src++)\
if (!(++i & mask))\
*dst##BITS++ = *(const uint##BITS##_t *restrict)(src - align);\
dst = (char*)dst##BITS;\
} while (0)
if (align & 8) {
ALIGNED_STRING_COPY_IMPL_(64);
} else if (align & 4) {
ALIGNED_STRING_COPY_IMPL_(32);
} else if (align & 2) {
ALIGNED_STRING_COPY_IMPL_(16);
} else { // byte-aligned
while ((*dst++ = *src++))
++i;
return i;
}
const size_t offset = (i & mask) + 1;
memcpy(dst, src - offset, offset);
return i;
}
#ifdef __cplusplus
}
#endif
答: 暂无答案
评论