C ++ W: использование запущенного образа дочернего потока - PullRequest
0 голосов
/ 05 октября 2018

сообщение об ошибке:
Программа остановлена ​​на 0x77dc2f6a
Она остановилась с сигналом SIGSEGV, Ошибка сегментации.
(gdb) Использование рабочего образа дочернего потока 2120.0x20d8.Программа остановлена ​​на 0x77dc2f6a
Она остановилась с сигналом SIGSEGV, ошибка сегментации.

complier: C-Free

вот мои коды

#include<stdio.h>

using namespace std;

/*
128m
n: [6,40] k: [1,6]
n*k: 0.9k
*/

struct BN
{
    char num[160];
    int len;
};

int len, num_k;
BN number;
BN* map;
bool* isC;

void BN_get(BN* bn, int len);
void BN_show(BN* bn);
void BN_clear(BN* bn);

// compare
bool BN_gt(BN* a, BN* b);

// count
void BN_mul(BN* a, BN* b, BN* c, int aS, int aE, int bS, int bE);//c = a+b

void f(int n, int k);

int main()
{
    int i, j;
    char c;

    scanf("%d  %d", &len, &num_k);
    BN_get(&number, len);

    map = new BN[len*num_k];
    isC = new bool[len*num_k];

    for(i=0;i<len*num_k;++i)
        isC[i]=false;

    // init
    for(i=0; i<len; ++i){
        //map[i,0]
        for(j=0;j<=i;++j){
            map[i*num_k].num[j] = number.num[j];
        }
        map[i*num_k].len = i+1;
        isC[i*num_k] = true;
    }

    //printf("");//case1
    f(len-1, num_k);

    BN_show(&map[len*num_k]);

    return 0; // line 63
}

void BN_get(BN* bn, int len)
{
    int i;
    char c;
    c = getchar();
    for(i=len-1;i>=0;--i){
        scanf("%c", &c);
        if(i>159 || i<0)printf("OUT\n");//debug
        bn->num[i] = c-'0';
    }// line 85
    bn->len = len;
}

void BN_show(BN* bn)
{
    int i, len=bn->len;
    for(i=len-1;i>=0;--i){
        if(i>159 || i<0)printf("OUT\n");//debug
        printf("%d", bn->num[i]);
    }
}

void BN_clear(BN* bn)
{
    int i;
    for(i=0;i<160;++i){
        if(i>159 || i<0)printf("OUT\n");//debug
        bn->num[i]=0;
    }

    bn->len = 0;
}

bool BN_gt(BN* a, BN* b)
{
    int i, an, bn;
    int alen = a->len, blen=b->len;
    // if a>b
    if(blen>alen){
        return false;
    }else if(alen==blen){
        for(i=alen-1; i>=0; --i){
            if(i>159 || i<0)printf("OUT\n");//debug
            an = a->num[i];
            bn = b->num[i];
            if(an>bn)
                return true;
            if(an<bn)
                return false;
        }
        return false;
    }
    return true;
}

void BN_mul(BN* a, BN* b, BN* c, int aS, int aE, int bS, int bE)
{
    int i, j, k, l;
    char *an=a->num, *bn=b->num, *cn=c->num;

    BN_clear(c);

    for(i=bS, k=0; i<=bE; ++i, ++k){
        for(j=aS,l=k; j<=aE; ++j,++l){
            if(i>159 || i<0)printf("OUT\n");//debug
            if(l>159 || l<0)printf("OUT\n");//debug
            if(j>159 || j<0)printf("OUT\n");//debug
            if(l+1>159 || l+1<0)printf("OUT\n");//debug
            cn[l] += bn[i]*an[j];
            cn[l+1] += cn[l]/10;
            cn[l] %= 10;
        }
    }
    if(l>159 || l<0)printf("OUT\n");//debug
    if(cn[l]==0)
        c->len = l;
    else
        c->len = l+1;
}

void f(int n, int k)
{
    int i, up=n-1-(k-2);
    BN max, a, b;

    BN_clear(&max);

    for(i=0;i<up;++i){
        // b = f(n-1-i, k-1)
        if(!isC[(n-1-i)*num_k+k-1])
            f(n-1-i, k-1);
        b = map[(n-1-i)*num_k+k-1];

        // a = f(n-1-i, k-1) x num(n-i, n);
        BN_mul(&b, &number, &a, 0, b.len-1, n-i, n);

        // max
        if(BN_gt(&a, &max))
            max=a;
    }

    isC[n*num_k+k] = true;
    map[n*num_k+k] = max;
}

BN_xxx () isнекоторые операции с большим числом
В конце main, вот строка кода

"//printf("");//case1"

Если я не printf (), я получу неправильное сообщение.
Если я printf(), даже если печать пустая, она будет работать без ошибок.

Я установил много проверок, и он видит, что никогда не выходит за пределы диапазона.
Я полагаю, что проблема связана с потоком ввода-вывода, но я нене знаю, что случилось.

Я снова запускаюсь в msvs.Вот этот стек

name                            language
ntdll.dll!00007ffbc22d4cfa()    unknown
ntdll.dll!00007ffbc22dc806()    unknown
ntdll.dll!00007ffbc22dcad1()    unknown
ntdll.dll!00007ffbc2279a55()    unknown
ntdll.dll!00007ffbc21f6db5()    unknown
ntdll.dll!00007ffbc21f2b55()    unknown
ucrtbased.dll!00007ffb6a341716()    unknown
ucrtbased.dll!00007ffb6a3414cd()    unknown
ucrtbased.dll!00007ffb6a34455f()    unknown
ucrtbased.dll!00007ffb6a3a622b()    unknown
ucrtbased.dll!00007ffb6a368e15()    unknown
ucrtbased.dll!00007ffb6a3857c6()    unknown
ucrtbased.dll!00007ffb6a37c085()    unknown
ucrtbased.dll!00007ffb6a37c27b()    unknown
ucrtbased.dll!00007ffb6a37cbd7()    unknown
ucrtbased.dll!00007ffb6a39ea3b()    unknown
ConsoleApplication1.exe!_vfprintf_l(_iobuf * const _Stream, const char * const _Format, __crt_locale_pointers * const _Locale, char * _ArgList) line 644    C++
ConsoleApplication1.exe!printf(const char * const _Format, ...) line 958    C++
ConsoleApplication1.exe!BN_show(BN * bn) line 85    C++
ConsoleApplication1.exe!main() line 63  C++

1 Ответ

0 голосов
/ 05 октября 2018

Вы выделяете память:

map = new BN[len*num_k];

Это эффективно создает массив с индексами 0 до len*num_k - 1 (включительно) и заставляет map указывать на первый элемент этого массива.

Затем вы вызываете BN_show:

BN_show(&map[len*num_k]);

В функцию вы передаете указатель на структуру с индексом len*num_k, который один за концом выделенного массива! Выход за пределы приводит к неопределенному поведению .

Указатель, который вы передаете функции BN_show, просто недействителен, и вам нужно изменить свойкод для передачи указателя на действительную структуру.

Если вы хотите напечатать все элементы массива map, используйте над ним цикл и вызовите BN_show для каждого элемента отдельно.


По сопутствующему примечанию: не выполняйте ручное распределение массивов, используйте std::vector.

Я также рекомендую прекратить использование указателей, и вместо этогоиспользуйте либо объект («значения») напрямую, либо ссылки.

Наконец, пожалуйста получитеНесколько хороших книг по C ++ и выучите их правильно.Сейчас кажется, что вы используете его скорее как улучшенный компилятор Си.

...