Время от времени программа аварийно завершает работу при использовании free для указателя, содержащего условно выделенную память.

Это простой код, просто чтобы проиллюстрировать проблему, с которой я имею дело.

Если вы дадите ввод n = 3 и введете элементы массива как 1, 2 ,3 и m = 0, программа вылетит!! !

Почему это так?? Проблема возникает из-за того, что последние 2 строки содержат функцию free().

Теперь мой вопрос: почему это происходит? Та же программа с тем же входом не падает, если удалить операторы free...

Пожалуйста, объясните мне. Является ли причиной возникновения указанной проблемы условное выделение памяти?? Если да, то почему?

Я не получаю никакой подсказки, более того, свободное (NULL) не должно вызывать никаких ошибок, насколько я знаю, поэтому проблема возникает, когда я пытаюсь освободить одну из выделенных памяти, особенно положительные в мой вклад...

Это мой код:

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

int main()
{
    int n;
    scanf("%d",&n);
    printf("Enter elements into the array\n");
    int arr[n];
    int i;
    for(i=0;i<n;)
    {
        printf("arr[%d] ? ",i);
        scanf("%d",(arr+i));
        if(i>0)
        {
            if(arr[i]<arr[i-1])
                continue;
            else
                i++;
        }
        else
            i++;
    }
    int m;
    printf("m ? ");
    scanf("%d",&m);
    int j,flag=0;
    int *positive,*negative;
    int start,end;
    start=arr[0];
    end=arr[n-1];
    if(start<0 && end<0)
    {
        negative=(int*)calloc((start*-1),sizeof(int));
        positive=0;
    }
    else if(start<0 && end>0)
    {
        negative=(int*)calloc((start*-1),sizeof(int));
        positive=(int*)calloc(end,sizeof(int));
    }
    else if(start>=0 && end >0)
    {
        negative=0;
        positive=(int*)calloc(end,sizeof(int));  
    }
    int p=0;
    for(i=0;i<n;i++)
    {
        if(i==0)
            p=-1;
        else
            p=i;
        if(arr[i]<0)
            negative[-arr[i]]=p;
        else
            positive[arr[i]]=p;
    }
    for(i=0;i<n;i++)
    {
        int num=m-arr[i];
        if(negative!=0 && num<0 && negative[-num])
        {
            if(negative[-num]==-1)
                j=0;
            else
                j=negative[-num];
            printf("%d %d\n",i,j);
            flag=1;
        }
        else if(positive!=0 && num>=0 && positive[num])
        {
            if(positive[num]==-1)
                j=0;
            else
                j=positive[num];
            printf("%d %d\n",i,j);
            flag=1;
        }
    }
    if(flag==0)
        printf("NO SUCH i j EXISTS\n");
    if(positive) free(positive);
    if(negative) free(negative);
    return 0;
}

Вот мой вывод:

введите здесь описание изображения


person Community    schedule 21.03.2019    source источник
comment
Вы выходите за пределы любого из массивов (динамически выделенных или нет)? Вы разыменовываете positive или negative, даже если они NULL? Пробовали ли вы пройтись по коду построчно в отладчике, чтобы убедиться, что он ведет себя так, как должен?   -  person Some programmer dude    schedule 21.03.2019
comment
К вашему сведению, вам не нужны if(positive) или if(negative). free() делает эту проверку самостоятельно.   -  person Barmar    schedule 21.03.2019
comment
Я сделал это, чтобы быть более уверенным, что free(NULL) не вызывает ошибки   -  person    schedule 21.03.2019
comment
Кроме того, что произойдет, если end == 0? Тогда ваши указатели будут неинициализированы.   -  person Some programmer dude    schedule 21.03.2019
comment
Может ли end быть 0? Ваши блоки if и else if обрабатывают только end < 0 и end > 0, но не end == 0.   -  person Barmar    schedule 21.03.2019
comment
Запуск кода в Valgrind должен выявить проблему. К сожалению, Valgrind не установлен в системе, которую я сейчас использую.   -  person taskinoor    schedule 21.03.2019


Ответы (1)


С входными значениями, которые вы упомянули, вы сначала выполните:

end=arr[n-1];
positive=(int*)calloc(end,sizeof(int));

Учитывая, что n == 3 и arr[n-1] == 3, вы выделяете массив из 3 int для positive.

В следующем цикле вы делаете:

positive[arr[i]]=p;

который пытается перезаписать positive[3] (когда i == n-1). Это попытка записи за пределы массива (допустимые индексы варьируются только от 0 до 2) и неопределенное поведение означает, что после этого момента может произойти что угодно, включая сбой.

person Sander De Dycker    schedule 21.03.2019