首页 > 解决方案 > C++ W:使用子线程的运行映像

问题描述

错误消息:
程序在 0x77dc2f6a 处
停止它以 SIGSEGV 信号停止,分段错误。
(gdb) 使用子线程 2120.0x20d8 的运行镜像。程序在 0x77dc2f6a 处
停止它以 SIGSEGV 信号停止,分段错误。

编译器: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() 是大数的一些操作
在 main 的末尾,这是代码行

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

如果我不 printf(),我将收到错误消息。
如果我 printf(),即使打印空,它也不会出错。

我设置了很多检查,它认为永远不会超出范围。
我猜这个问题是关于 IO 流的,但我不知道发生了什么。

我再次在 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++

标签: c++streamsegmentation-fault

解决方案


你分配内存:

map = new BN[len*num_k];

这有效地创建了一个索引0len*num_k - 1(包括)的数组,并map指向该数组的第一个元素。

然后你打电话BN_show

BN_show(&map[len*num_k]);

向函数传递一个指向索引处结构的指针,该结构len*num_k超出分配的数组的末尾!越界会导致未定义的行为

您传递给BN_show函数的指针根本无效,您需要修改代码以将指针传递给有效结构。

如果要打印map数组的所有元素,请在其上使用循环,并BN_show分别调用每个元素。


在相关的旁注中:不要手动分配数组,std::vector而是使用。

我还建议您停止使用指针,而是直接使用对象(“值”)或引用。

最后,请找几本关于C++的好书,好好学习。现在,您似乎更多地将它用作增强的 C 编译器。


推荐阅读