Ошибка вызвана функцией, которая еще не была запущена - PullRequest
0 голосов
/ 15 января 2019

Итак, я пишу систему обработки счетов. Данные в настоящее время находятся в структуре Stack, которую я написал.

У меня есть эта частично написанная функция, которая записывает отчет:

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

Что отлично работает, пока я оставляю вторую строку закомментированной. Если я раскомментирую его, я получаю ошибку SIGSEGV в функции PrintBillHeading(), как указано ниже.

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 голосов
/ 15 января 2019

В дополнение к правильному ответу от AlexP, я хотел бы отметить еще одно (скрытое) неопределенное поведение:

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

Теперь CollapseCallStack в вашей текущей реализации ничего не возвращает .Он будет по-прежнему вызываться, и на самом деле что-то будет назначено вашему указателю collatedEntries при вашей инициализации.

Проблема в том, что при вызове CollapseCallStack выделяется память для возвращаемого значения,но ему никогда не присваивается значимое значение, поскольку оператор return отсутствует.Таким образом, по существу ваш collatedEntries указатель будет инициализирован случайным значением мусора, и если вы попытаетесь разыменовать его, это вызовет UB.

0 голосов
/ 15 января 2019

В функции PrintBillHeading() оператор strcpy(addressCpy,bill->address) использует значение неинициализированной переменной addressCpy. Это неопределенное поведение. Неопределенное поведение означает, что программа может произойти сбой в любом случайном месте. Если программа содержит неопределенное поведение , то вся программа недействительна .

...