место изменения переменной? - PullRequest
0 голосов
/ 09 ноября 2018

У меня есть некоторый код, но по какой-то причине расположение переменной меняется в середине моего кода. В основном я читаю одно целое число из stdin, а затем malloc массив структур.

int main(){
    int numcities;
    scanf("%d", &numcities);

    City **cities = malloc(numcities*sizeof(City)*2); //*2 is just to be sure, gonna remove that later.

    for(int n = 0;n<numcities;n++){
        int nularr[numcities];
        for(int n2 = 0;n2<numcities;n2++){
            nularr[n2] = 0;
        }
        City c = {
            .value = 1,
            .options = nularr,
        };
        cities[n] = &c;
    };

    readRoads(cities, numcities);
}

readRoads показано ниже. перед вызовом readRoads я могу получить доступ к numcities (gdb и внутри кода), но после sigsegvs при попытке его использовать и в gdb жалуется на невозможность чтения памяти в 0xffffffcd. Если я возьму указатель на числа и разыменую его позже, все будет в порядке. но получение указателя после вызова readRoads дает мне 0xffffffcd (последовательно), который не читается. Я уже получаю от malloc вдвое больше памяти, чем необходимо,

void readRoads(City **cities, int N){
    for(int n = 0;n<N;n++){
        int buf;
        int res[N];
        int roads = 0;
        City *options[N];
        scanf("%d", &buf);
        for(int r = 0;r<N;r++){
            res[r]= buf << r;
            if(res[r]){
                options[roads] = cities[r];
                roads++;
            }
        }

        cities[n]->id = n;
        cities[n]->name = n +'A';
        cities[n]->optionsCount = 1;

        for(int i = 0; i < roads; i++){
            cities[n]->options[i] = options[i]->id;
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 09 ноября 2018

Когда вы присваиваете массиву cities:

for(int n = 0;n<numcities;n++){
    int nularr[numcities];
    for(int n2 = 0;n2<numcities;n2++){
        nularr[n2] = 0;
    }
    City c = {
        .value = 1,
        .options = nularr,
    };
    cities[n] = &c;
};

Вы назначаете адрес локальной переменной. Эта переменная выходит из области видимости в конце цикла for, поэтому вы в конечном итоге указываете на недопустимую память. Разыменование этого недействительного указателя вызывает неопределенное поведение . То же самое происходит, когда вы присваиваете nularr одному из этих экземпляров

Вместо создания массива указателей на City, просто создайте массив City. Также вам нужно будет динамически распределять nularr.

City *cities = malloc(numcities*sizeof(City));

for(int n = 0;n<numcities;n++){
    int *nularr = calloc(numcities, sizeof(int);
    cities[n].value = 1;
    cities[n].options = nularr;
};

Также измените readRoads соответственно:

void readRoads(City *cities, int N){
    ...

И обязательно проверьте возвращаемое значение malloc / calloc на наличие ошибок.

0 голосов
/ 09 ноября 2018
    City c = {
        .value = 1,
        .options = nularr,
    };
    cities[n] = &c;
}

При этом }, c выходит из области видимости и перестает существовать (это локальная переменная в этом блоке).

Указатель, который вы только что сохранили (cities[n]), стал неопределенным.

По сути, теперь города представляют собой массив недействительных указателей.


(Кроме того, он должен быть инициализирован как

City **cities = malloc(numcities * sizeof (City *));

В частности, sizeof (City *), а не sizeof (City).)

...