Функция выдаёт желаемый результат и затем ненормально завершает работу - PullRequest
3 голосов
/ 31 марта 2020

Я написал следующую программу:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* reversenew(char*);
char* reverseold(char*);
char* add(char*,char*);
char* standard(char*);

int main()
{
    int i,n;
    char *num1, *num2;
    num1 = malloc(1000*sizeof(char));
    num2 = malloc(1000*sizeof(char));
    printf("Enter the numbers to be added\n");
    gets(num1);
    gets(num2);
    printf("\n%s\n",add(num1,num2));
    return 0;
}

char* reversenew(char* m)
{
    char *k;
    k = malloc(100*sizeof(char));
    strcpy(k,m);
    int i,n = strlen(k);
    for(i = 0;i<n;i++)
    k[i] = m[n-i-1];
    return(k);
}

char* reverseold(char* m)
{
    char temp;
    int i,n = strlen(m);
    for(i=0;i<n/2;i++)
    {
        temp = m[i];
        m[i] = m[n-i-1];
        m[n-i-1] = temp;
    }
    return m;
}

char* add(char* num1,char* num2)
{
    char *n1,*n2;
    int i,digit,carry = 0;
    n1 = reversenew(standard(num1));
    n2 = reverseold(standard(num2));
    int n = (strlen(n1)>strlen(n2))?strlen(n1)+1:strlen(n2)+1;
    while(strlen(n1)!=strlen(n2))
    (strlen(n1)>strlen(n2))?(n2 = strcat(n2,"0")):(n1 = strcat(n1,"0"));
    n1 = strcat(n1,"0");
    n2 = strcat(n2,"0");
    for(i=0;i<n;i++)
    {
        digit = (int)n1[i]+(int)n2[i]+carry-96;
        n1[i] = (char)(48+(digit%10));
        carry = digit/10;
    }
    n1 = reverseold(n1);
    n2 = reverseold(n2);
    if(n1[0] == 48)
    n1++;
    strcpy(n2,standard(n2));
    return(n1);
}

char* standard(char* m)
{
    int i = 0;
    while(i < strlen(m))
    {
        if(m[0] == 48)
        m+=1;
        else
        break;      
    }
    return m;
}

Функция add добавляет два натуральных числа в виде строки и возвращает результат в виде строки. Эта функция дает желаемый результат, а затем выходит с возвращаемым значением 0 для небольших входов и выходит с возвращаемым значением 3221226356 для больших входов (скажем, для входных строк длиной 140). Я взял 9 повторений 140 раз, чтобы добавить к одному и тому же номеру.

Обратите внимание, что функция reversenew инвертирует строку и сохраняет результат в новой строке, сохраняя исходное многократное использование, в то время как функция reverseold переворачивает исходную строку.

Также, если я отредактирую и введу printf("\n5"); непосредственно перед return 0; после предыдущей строки, то она будет напечатана в окне вывода, как и ожидалось, и поэтому я прихожу к выводу, что add функция работает правильно.

Пожалуйста, помогите мне разобраться в проблеме.

1 Ответ

4 голосов
/ 31 марта 2020

Когда я запускаю вашу программу с valgrind и ввожу следующие цифры

123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890

Я получаю эти сообщения об ошибках

==5279== Invalid write of size 1
==5279==    at 0x483E0AC: strcpy (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==5279==    by 0x10929D: reversenew (add.c:27)
==5279==    by 0x1093B0: add (add.c:51)
==5279==    by 0x109251: main (add.c:19)
==5279==  Address 0x4a5b184 is 0 bytes after a block of size 100 alloc'd
==5279==    at 0x483A7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==5279==    by 0x109286: reversenew (add.c:26)
==5279==    by 0x1093B0: add (add.c:51)
==5279==    by 0x109251: main (add.c:19)
==5279== 

valgrind: m_mallocfree.c:305 (get_bszB_as_is): Assertion 'bszB_lo == bszB_hi' failed.
valgrind: Heap block lo/hi size mismatch: lo = 176, hi = 3761405300628338743.
This is probably caused by your program erroneously writing past the
end of a heap block and corrupting heap metadata.  If you fix any
invalid writes reported by Memcheck, this assertion failure will
probably go away.  Please try that before reporting this as a bug.

В функции reversenew вы выделяете блок 100 байтов независимо от длины строки и запишите в нее данные в размере исходной строки.

Это неопределенное поведение.

Ваша add функция работает правильно, потому что эта функция и последующие printf не заботятся о том, что вы написали после конца выделенной области памяти.

Когда функция main вернется, система автоматически очистит ресурсы, например, освободит всю память и закроет все файлы. В вашем случае странные вещи происходят в этот момент, потому что вы уничтожили некоторые внутренние данные динамического распределения памяти. Вы видите странное возвращаемое значение в результате. Это также может привести к нарушению доступа или к чему-либо или к чему-то другому, так как это undefined .

Выделите правильный размер для строки результата в reversenew.

...