malloc прави странни неща с адресите на паметта

Правя сортиране на кофа, сортирайки указатели към възли в свързан списък с фиктивна заглавка. Потребителят въвежда стойностите за възлите и след това те веднага се пускат в съответната кофа. Проблемът ми възниква, когато се опитвам да разпределя паметта за втория възел (без да включвам фиктивната заглавка) за свързания списък.

Това е кодът, използван за пускане на възлите в кофата, като var е стойността, която се сортира, а current е новосъздаденият възел, който трябва да бъде сортиран:

void bucketSort(int var, nodeptr current)
    if(!bucket[var])
    {
    buckets[var] = (nodeptr) malloc(sizeof(nodeptr));
    buckets[var]->next = current;
    bucketrear[var] = current;
    }
    else
    {
    bucketrear[var]->next = current;
    bucketrear[var] = current;
    }
}

Това е опростена версия (по-малко стойности) на кода, използван за създаване на новия възел:

void addNode(int value)
{
    nodeptr newNode;

    newNode= (nodeptr) malloc(sizeof(nodeptr));

    newNode->value = value;
    newNode->next = NULL;


    bucketDrop(value, newNode);
} 

С изразите за проследяване открих, че преди Malloc на втория възел (със същата стойност като първия), адресът на bucket[value]->next беше нормален адрес, но след това адресът беше 17. Тази стойност от 17 се появи във всеки един тест, който направих.

Всяка помощ или идеи биха били чудесни. Благодаря ви предварително.


person Thaotic    schedule 28.05.2013    source източник
comment
sizeof nodeptr? Нямате ли предвид sizeof node или sizeof *newNode?   -  person Zeta    schedule 28.05.2013
comment
Можете ли да поставите и вашия sctruc?   -  person Maresh    schedule 28.05.2013
comment
Ако паметта ви се презаписва, тогава първо проверете дали не използвате указатели към локални променливи, които записвате. Също така препоръчвам инструменти като Valgrind.   -  person Some programmer dude    schedule 28.05.2013
comment
Освен грешката, вече идентифицирана от Zeta, в C (различен от C++) не трябва да предавате връщането на malloc, това може да скрие фини грешки.   -  person Jens Gustedt    schedule 28.05.2013


Отговори (3)


Мисля, че това е едно от решенията.

buckets[var] = (nodeptr) malloc(sizeof(*buckets[var]));

newNode= (nodeptr) malloc(sizeof(*newNode));
person HS Song    schedule 28.05.2013
comment
Благодаря ви, това го поправи. Използвах malloc, който беше предоставен в лекциите, и моят преподавател ме увери, че е правилен. - person Thaotic; 29.05.2013

Вие смесвате структурата за вашия възел и указателя, сочещ към него, и по този начин презаписвате местоположението на паметта.

Тъй като прехвърляте резултата malloc към тип nodeptr, това означава, че това е указател (тъй като malloc() връща указател), което също означава, че разпределяте памет с размера на указател.

И така, като се има предвид, че сте кръстили структурата си nodestruct, за да разпределите достатъчно памет, ще пишете

newNode = (nodeptr) malloc(sizeof(struct nodestruct));
person grasbueschel    schedule 28.05.2013
comment
Моля, не прехвърляйте върнатата стойност на malloc() в C. И мисля, че използването на sizeof *newNode би било по-малко податливо на грешки от sizeof(struct nodestruct), но може да се спори, предполагам. - person Remi Gacogne; 28.05.2013
comment
@RemiGacogne защо не прехвърлите върнатата стойност на malloc? Ако не искате да използвате само void* в кода си, все пак ще трябва да кастнете в някакъв момент?! - person grasbueschel; 29.05.2013
comment
След ANSI C указателят на void може да бъде присвоен на всеки тип указател безопасно, без необходимост от кастинг. Така че вече не е необходимо и тъй като всяко преобразуване може да попречи на компилатора да ви предупреди за грешка по-късно, не трябва да се използва. - person Remi Gacogne; 29.05.2013

Следното трябва да разреши проблема ви:

newNode= (nodeptr) malloc(sizeof(*nodeptr));

Причината е, че nodeptr изглежда като указател към структура и следователно трябва да разпределите памет за структурата вместо указател.

От следващия път, моля, поставете и структурните си дефиниции.

person cosmos    schedule 28.05.2013