@Georgy123

Как найти неправильную работу с памятью?

Суть проблемы такова: когда в txt файле на вход подается число -8147483645 программа выдает неправильный ответ (когда, например при выборе "+1" выдается число 442450948). Насколько я понял, это какой-то косяк в моей работе с памятью. Удалось выяснить, что где-то в функции num_convert происходит переполнение памяти, отсюда идет неправильный ответ. Но где именно это происходит выяснить не получилось, поэтому прошу помощи в обнаружении проблемы. Привожу, собственно, сам код:

функция num_convert просто каждую цифру числа перемещает в массив

void num_convert(long long int num, int ord, long long int* mas, long long int** p)
{

    int counter=ord;
    printf("num %lld\n",num);
    int flag=0;
    int sign=num/abs(num);
    num=abs(num);
    mas=realloc(mas,(ord+1)*sizeof(long long int));
    while (1==1)
    {
        if (num/10==0 && flag==1)
        {
            break;
        }

        if (num/10==0 && flag==0)
        {
            mas[0]=num%10;
            flag++;
        }
        else
        {
            mas[counter]=num%10;
            num=num/10;
            counter--;
        }
    }
    if (sign==-1)
    {
        mas[0]=-1*mas[0];
    }
    *p=mas;
}


Далее приведена функция, ответственная за "взаимодействие с пользователем",ее привожу, чтобы было примерно понятно, что вообще происходит в программе и где что может сломаться.

int main(void)
{

    long long int** p;
    long long int *m;
    int sw=0;
    int size=0;
    int ord=0;
    long long int n=0;
    int o=0;
    char file_name[255];
    m=(long long int* )malloc(sizeof(long long int));
    p=&m;


    printf("Choose one of the options:\n");
    printf("Enter 1 if you have the number of the elements in your file\n");
    printf("Enter 2 if you do not have the number of the elements in your file\n");
    printf("Enter 3 to shut down the program\n");
    printf(":");
    scanf("%d",&sw);

    switch(sw)
    {
        case(3):
            free(m);
            return 0;
        case(1):
            printf("Enter the name of the file \n");
            scanf("%s", file_name);
            size=read_1(m,file_name,p);
            break;
        case(2):
            printf("Enter the name of the file \n");
            scanf("%s", file_name);
            size=read_2(m,file_name,p);
            break;
    }

    if (size<1)
    {
        printf("An error occured\n");
        free(m);
        return -1;
    }

    n=arr_convert(m,size);
    ord=get_ord(n);
    printf("Choose the scenario (enter +1 or -1) \n");
    scanf("%d",&o);

    switch(o)
    {
        case(1):
            n=n+1;
            ord=get_ord(n);
            num_convert(n,ord,m,p);
            for (int y=0;y<=ord;y++)
            {
                printf("%lld ",m[y]);
            }
            free(m);
            return 0;
        case(-1):
            n=n+1;
            ord=get_ord(n);
            num_convert(n,ord,m,p);
            for (int y=0;y<=ord;y++)
            {
                printf("%lld ",m[y]);
            }
            free(m);
            return 0;
    }
}


А таков вывод valgrind

==6016== Invalid write of size 8
==6016==    at 0x109467: num_convert (in /home/georgy/Рабочий стол/5 домашка/progr)
==6016==    by 0x108CDC: main (in /home/georgy/Рабочий стол/5 домашка/progr)
==6016==  Address 0x55ccc90 is 16 bytes after a block of size 48 in arena "client"
==6016== 
==6016== Conditional jump or move depends on uninitialised value(s)
==6016==    at 0x523696A: vfprintf (vfprintf.c:1642)
==6016==    by 0x523EFA5: printf (printf.c:33)
==6016==    by 0x108D16: main (in /home/georgy/Рабочий стол/5 домашка/progr)
==6016== 
==6016== Use of uninitialised value of size 8
==6016==    at 0x52328FB: _itoa_word (_itoa.c:179)
==6016==    by 0x5235F9D: vfprintf (vfprintf.c:1642)
==6016==    by 0x523EFA5: printf (printf.c:33)
==6016==    by 0x108D16: main (in /home/georgy/Рабочий стол/5 домашка/progr)
==6016== 
==6016== Conditional jump or move depends on uninitialised value(s)
==6016==    at 0x5232905: _itoa_word (_itoa.c:179)
==6016==    by 0x5235F9D: vfprintf (vfprintf.c:1642)
==6016==    by 0x523EFA5: printf (printf.c:33)
==6016==    by 0x108D16: main (in /home/georgy/Рабочий стол/5 домашка/progr)
==6016== 
==6016== Conditional jump or move depends on uninitialised value(s)
==6016==    at 0x52360A4: vfprintf (vfprintf.c:1642)
==6016==    by 0x523EFA5: printf (printf.c:33)
==6016==    by 0x108D16: main (in /home/georgy/Рабочий стол/5 домашка/progr)
==6016== 
==6016== Conditional jump or move depends on uninitialised value(s)
==6016==    at 0x5236BDC: vfprintf (vfprintf.c:1642)
==6016==    by 0x523EFA5: printf (printf.c:33)
==6016==    by 0x108D16: main (in /home/georgy/Рабочий стол/5 домашка/progr)
==6016== 
==6016== Invalid read of size 8
==6016==    at 0x108D00: main (in /home/georgy/Рабочий стол/5 домашка/progr)
==6016==  Address 0x55ccc78 is 4 bytes after a block of size 36 alloc'd
==6016==    at 0x4C31D2F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6016==    by 0x1093AA: num_convert (in /home/georgy/Рабочий стол/5 домашка/progr)
==6016==    by 0x108CDC: main (in /home/georgy/Рабочий стол/5 домашка/progr)


Примечательно, что как таковых утечек памяти не происходит (со слов самого же valgrind)
  • Вопрос задан
  • 60 просмотров
Решения вопроса 1
jcmvbkbc
@jcmvbkbc
http://dilbert.com/strip/1998-08-24
Как найти неправильную работу с памятью?

Откомпилируй и слинкуй свою программу с опцией -g, тогда valgrind тебе прямо в проблемную строчку тыкнет.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
29 нояб. 2020, в 22:37
500 руб./за проект
29 нояб. 2020, в 20:54
3000 руб./за проект
29 нояб. 2020, в 20:40
25000 руб./за проект