C:调试和发布模式的差异

c: difference in debug and release mode?

本文关键字:模式 调试 布模式      更新时间:2023-10-16

我试图建立一个简单的库整数操作没有绑定(我知道GMP的存在,只是为了我自己的利益)。我通过教计算机用字符数组做小学算术来做到这一点。我知道这是一种非常低效的方式,但这是我能想到的,也是我正在做的。我已经成功地为所有四个+-*/操作编写了C代码,但不知何故只能在调试模式下。代码在GDB和Visual Studio 2013调试模式下都能很好地工作;我已经测试得够多了。但是,在发布模式下的正常执行过程中,它会不断抛出错误。我已经搜索了很多关于在调试期间未检测到的发布模式问题的主题,但我发现的解决方案似乎不适合我的情况,至少在我可以看到的范围内。

edit:我所说的'error'是指我的代码将执行'goto error;',这意味着计算结果是混乱的,所以它没有通过main()中给出的随机整数计算测试。这种错误并不总是发生,而是在释放模式中大约10~20次成功操作后发生。

在调试期间不会出现单个(任何一般)错误。

是我在代码中犯的一个非常简单的错误,一个简短的修复将使一切都很好吗?也许我的整个代码就是一团乱麻?是我的Windows 7系统有问题吗?或者其他可能的事情?我已尽我所能来处理这个问题,但现在我却无能为力。如有任何帮助,我将不胜感激。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define A_PLUS -1
#define A_MINUS -2
#define INT_LEN 10
typedef struct{
    int sign;
    int start;
    char *num;
} abn;
void initABN(abn *n);
void sInitABN(abn *n, char *cs);
void iInitABN(abn *n, int num);
void sReInitABN(abn *n, char *cs);
void iReInitABN(abn *n, int num);
void delABN(abn *n);
int aBigger(const abn *king, const abn *slave);
void aPlus(abn *t, const abn *a, const abn *b);
void aMinus(abn *t, const abn *a, const abn *b);
void printABN(const abn *a);
int abnToInt(const abn *a);
int iPow(int base, int exp);
int fromElse = 0;
int main(){
    srand((unsigned)time(NULL));
    printf("number of tests for each operation: ");
    int testN;
    scanf("%d", &testN);
    printf("n");
    abn a, b;
    initABN(&a); initABN(&b);
    int i, t1, t2;
    for (i = 0; i < testN; ++i){
        t1 = rand()*(2*(rand() % 2) - 1);
        t2 = rand()*(2*(rand() % 2) - 1);
        iReInitABN(&a, t1);
        iReInitABN(&b, t2);
        printABN(&a);
        printf(" + ");
        printABN(&b);
        printf(" = ");
        aPlus(&a, &a, &b);
        printABN(&a);
        if (t1 + t2 == abnToInt(&a)){
            printf(" TRUEn");
        }else{
            goto error;
        }
    }
    for (i = 0; i < testN; ++i){
        t1 = rand()*(2*(rand() % 2) - 1);
        t2 = rand()*(2*(rand() % 2) - 1);
        iReInitABN(&a, t1);
        iReInitABN(&b, t2);
        printABN(&a);
        printf(" - ");
        printABN(&b);
        printf(" = ");
        aMinus(&a, &a, &b);
        printABN(&a);
        if (t1 - t2 == abnToInt(&a)){
            printf(" TRUEn");
        }else{
            goto error;
        }
    }
    delABN(&a); delABN(&b);
    printf("Test Complete!n");
    return 0;
    error:
    printf("nERRORn");
    system("pause");
    return 1;
}
void initABN(abn *n){
    n->num = NULL;
}
void sInitABN(abn *n, char *cs){
    int i;
    for (i = 0; cs[i] != 0; ++i); --i;
    if (cs[0] == '-'){
        n->sign = A_MINUS;
        n->start = i - 1;
        n->num = (char*)malloc(i);
        for (; i > 0; --i){
            n->num[n->start - i + 1] = cs[i] - '0';
        }
    }else{
        n->sign = A_PLUS;
        n->start = i;
        n->num = (char*)malloc(i + 1);
        for (; i >= 0; --i){
            n->num[n->start - i] = cs[i] - '0';
        }
    }
}
void iInitABN(abn *n, int num){
    char *tempCs = (char*)malloc(INT_LEN + 1);
    sprintf(tempCs, "%d", num);
    sInitABN(n, tempCs);
    free(tempCs);
}
void sReInitABN(abn *n, char *cs){
    free(n->num);
    sInitABN(n, cs);
}
void iReInitABN(abn *n, int num){
    char *tempCs = (char*)malloc(INT_LEN + 1);
    sprintf(tempCs, "%d", num);
    sReInitABN(n, tempCs);
    free(tempCs);
}
void delABN(abn *n){
    free(n->num);
    n->num = NULL;
}
int aBigger(const abn *king, const abn *slave){
    int kingSize = king->start, slaveSize = slave->start;
    if (kingSize > slaveSize){
        return 1;
    }
    if (kingSize < slaveSize){
        return 0;
    }
    int i;
    for (i = kingSize; i >= 0; --i){
        if (king->num[i] > slave->num[i]){
            return 1;
        }
        if (king->num[i] < slave->num[i]){
            return 0;
        }
    }
    return 0;
}
void aPlus(abn *t, const abn *a, const abn *b){
    int aSign = a->sign, bSign = b->sign;
    if (!fromElse){
        if (aSign != bSign){
            fromElse = 1;
            aMinus(t, a, b);
            fromElse = 0;
            return;
        }
    }
    char *temp;
    int aStart = a->start, bStart = b->start;
    if (aStart > bStart){
        t->start = aStart + 1;
        temp = (char*)calloc(aStart + 2, 1);
    }else{
        t->start = bStart + 1;
        temp = (char*)calloc(bStart + 2, 1);
    }
    int i, j;
    for (i = 0; i <= aStart; ++i){
        temp[i] += a->num[i];
    }
    for (i = 0; i <= bStart; ++i){
        temp[i] += b->num[i];
        if (temp[i] >= 10){
            temp[i] -= 10;
            ++temp[i + 1];
            for (j = i + 1; ; ++j){
                if (temp[j] >= 10){
                    temp[j] -= 10;
                    ++temp[j + 1];
                }else{
                    break;
                }
            }
        }
    }
    if (temp[t->start] == 0){
        --t->start;
    }
    if (aSign == A_PLUS){
        t->sign = A_PLUS;
    }else{
        t->sign = A_MINUS;
    }
    free(t->num);
    t->num = temp;
}
void aMinus(abn *t, const abn *a, const abn *b){
    int aSign = a->sign, bSign = b->sign;
    if (!fromElse){
        if (aSign != bSign){
            fromElse = 1;
            aPlus(t, a, b);
            fromElse = 0;
            return;
        }
    }
    char *temp;
    int aStart = a->start, bStart = b->start;
    if (aStart > bStart){
        t->start = aStart;
        temp = (char*)calloc(aStart + 1, 1);
    }else{
        t->start = bStart;
        temp = (char*)calloc(bStart + 1, 1);
    }
    int i;
    #define MIN_CALC(A, B)
        for (i = 0; i <= A##Start; ++i){
            temp[i] += A->num[i];
        }
        for (i = 0; i <= B##Start; ++i){
            temp[i] -= B->num[i];
            if (temp[i] < 0){
                temp[i] += 10;
                temp[i + 1] -= 1;
            }
        }
    if (aBigger(a, b)){
        MIN_CALC(a, b);
        if (aSign == A_PLUS){
            t->sign = A_PLUS;
        }else{
            t->sign = A_MINUS;
        }
    }else{
        MIN_CALC(b, a);
        if (aSign == A_PLUS){
            t->sign = A_MINUS;
        }else{
            t->sign = A_PLUS;
        }
    }
    for (i = t->start; i > 0; --i){
        if (temp[i] == 0){
            --t->start;
        }else{
            break;
        }
    }
    free(t->num);
    t->num = temp;
}
void printABN(const abn *a){
    if (a->start == 0 && a->num[0] == 0){
        printf("0");
        return;
    }
    if (a->sign == A_MINUS){
        printf("-");
    }
    int i;
    for (i = a->start; i >= 0; --i){
        printf("%d", a->num[i]);
    }
}
int abnToInt(const abn *a){
    int i, n = 0;
    for (i = 0; i <= a->start; ++i){
        n += a->num[i]*iPow(10, i);
    }
    if (a->sign == A_MINUS){
        n *= -1;
    }
    return n;
}
int iPow(int base, int exp){
    int n = 1;
    int i;
    for (i = 0; i < exp; ++i){
        n *= base;
    }
    return n;
}

这是由于ta指向相同的值。修改t所指向的值,也会修改a所指向的值。

aMinus函数中,在调用aBigger时间接使用a->start的值。但是,您已经在前面的函数中更改了t->starta->start的值。

这里有三种解决这个问题的方法:

  1. 更改代码,以便对t->start的修改发生在函数的后面(将值保存到一个新的局部变量并在需要之前设置)修复该问题。我认为这是最好的办法。

  2. 更改aBigger函数以长度作为参数并使用aStartbstart作为值,但仍然意味着您已经更改了a->start,并且可能会忘记并更改代码以在将来使用a->start

  3. 更改调用,将加减法的结果放入不同的变量中。这是有效的,但它仍然意味着你的函数有潜在的漏洞。

我无法解释为什么它在调试模式下工作,或者在调试发布模式时,我将尝试逐步执行,看看是否可以进一步跟踪它。