微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

您如何发现或避免犯错?

如何解决您如何发现或避免犯错?

当我编写代码时,我创建的更常见的错误类别是一对一错误 (OBO)。在“真实”代码中,我在用 C 或 C++ 进行复杂的指针/迭代器算术时最常遇到这个问题,但有时我在面试和家庭作业(例如实现合并排序)问题中也遇到了问题,我使用了其他编程语言。

我的典型调试策略包括随机交换 <<=++varvar++ 并将 + 1- 1 附加到变量,直到该代码似乎有效。我很想知道存在哪些更好的策略或工具(例如静态分析、调试器/IDE 功能等)来发现 OBO。

我对诸如“避免 C 风格的循环”、“避免指针算术”、“以函数式风格编写代码”或“使用不同的编程语言”之类的 pat 答案并不特别感兴趣。是的,这些事情可以缓解这个问题,但并不总是可行的,而且它们也不能完全消除 OBO 的危险。

举个例子,我相信下面的代码strcpy(3) 的 C(或者它也是有效的 C++)实现,没有 OBO。但是正如您所看到的,OBO 可能会出现许多潜在的问题领域。有什么方法可以轻松确认它实际上没有 OBO 吗?

#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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。