【问题标题】:C++ W:using the running image of child threadC++ W:使用子线程的运行映像
【发布时间】:2018-10-05 20:56:44
【问题描述】:

错误信息:
程序停止在 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++

【问题讨论】:

  • 您在调试器中运行,这很好,但是在哪里发生了崩溃?如果你列出你的函数调用堆栈,你的代码在哪里崩溃?请告诉我们,也请编辑代码以在该行包含注释。
  • 我又在 msvs 中运行了,看起来......

标签: c++ stream segmentation-fault


【解决方案1】:

你分配内存:

map = new BN[len*num_k];

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

那你打电话BN_show:

BN_show(&map[len*num_k]);

向函数传递一个指向位于索引len*num_k 的结构的指针,该结构超出分配数组的末尾!越界导致undefined behavior。

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

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


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

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

最后请get a few good books on C++好好学习。现在,您似乎更多地将它用作增强型 C 编译器。

【讨论】:

  • 哦,谢谢。地图的范围应该是 len*(num_k+1)。这段代码是为了解决一个 dp 问题。现在问题已经解决了。非常感谢。你太小心了。非常感谢!!
  • 感谢您的建议,看来前路漫漫,我会继续努力的。
猜你喜欢
  • 2020-11-13
  • 2020-05-24
  • 1970-01-01
  • 2017-05-31
  • 1970-01-01
  • 1970-01-01
  • 2017-01-29
  • 2012-08-01
  • 2020-11-13
相关资源
最近更新 更多