由尚未运行的功能引起的错误

时间:2019-01-15 14:23:53

标签: c sigsegv

所以我正在写一个账单处理系统。目前,数据位于我编写的Stack结构中。

我有这个编写报告的部分编写功能:

void GenerateReport(Bill* bill)
{
     PrintBillHeading(bill);
     //CallEntry* collatedEntries = CollapseCallStack(bill->callEntries);
//TODO
}

只要我将第二行保留为注释,哪个就可以正常工作。如果取消注释,则在PrintBillHeading()函数中出现SIGSEGV错误,如下所示。

void PrintBillHeading(Bill* bill)
{
    printf("Big Brother Telecom\n");
    printf("Bill Date: %s\n\n",DateTimeToISOString(bill->date));
    printf("Contract Holder: %s %s\n", bill->title, bill->name);
    printf("Address:\n");
    char* addressSeg;
    char* addressCpy;
    strcpy(addressCpy,bill->address); //This line throws the SIGSEGV
    while ((addressSeg = strtok_r(addressCpy,";",&addressCpy)))
    {
        printf("%s\n\0",addressSeg);
    }
}

为了完整起见,这里是我的CollapseCallStack()函数,它是不完整的,完全未经测试的,可能不起作用。

CallEntry* CollapseCallStack(Stack* calls)
{
    int size = calls->topIndex;
    CallEntry* collatedSet = malloc(sizeof(CallEntry) * size);
    CallEntry* poppedCall;
    int curIndex = 0;
    while (PopStack(calls,poppedCall))
    {
        bool found = false;
        for (int i = 0; i < size; i++)
        {
            CallEntry* arrItem = collatedSet + i * sizeof(CallEntry);
            if (StringEquals(arrItem->phoneNumber,poppedCall->phoneNumber))
            {
                found = true;
                arrItem->minutes += poppedCall->minutes;
            }
        }
        if (!found)
        {
            memcpy(collatedSet,poppedCall,sizeof(CallEntry)); //
        }
    }
}

还有CallEntry结构:

typedef struct{
    char* phoneNumber;
    int minutes;
    DateTime* callDateTime;
} CallEntry;

我的问题是:尚未调用的函数如何导致SIGSEGV错误在程序中更早地表达?

一旦我克服了这一点,就可以自己调试CollapseCallStack()函数,尽管如果有人看到任何明显的问题,我希望对此发表评论。

2 个答案:

答案 0 :(得分:6)

在函数PrintBillHeading()中,语句strcpy(addressCpy,bill->address)使用未初始化的变量addressCpy的值。这是未定义的行为。未定义的行为意味着程序可能会在任何随机位置崩溃。如果程序包含未定义的行为整个程序无效

答案 1 :(得分:1)

除了AlexP的correct answer外,我还要指出另一种(潜伏的)未定义行为:

void GenerateReport(Bill* bill)
{
     PrintBillHeading(bill);
     CallEntry* collatedEntries = CollapseCallStack(bill->callEntries);
//TODO
}

现在,CollapseCallStack在您当前的实现中不返回任何内容。它仍然会被调用,并且实际上在初始化时会为您的collatedEntries指针分配一个东西。

问题在于,当调用CollapseCallStack时,正在分配返回值的内存,但是由于缺少return语句,因此从未分配有意义的值。因此,实际上,您的collatedEntries指针将使用随机垃圾值初始化,并且如果您尝试取消引用它,则会导致UB。