Обнаружен glibc - двойное освобождение или повреждение - PullRequest
3 голосов
/ 28 августа 2010

это может быть немного длинно, поэтому мои извинения.рассмотрим следующий код (я оставил некоторые несущественные части из него).этот код получает указатель на структуру (BoardP theBoard), координаты x & y и значение.цель состоит в том, чтобы поместить значение в двумерный массив, который находится в структуре.если координаты выходят за границы, я должен увеличить размер таблицы, скопировать старые данные в новые данные и поместить значение на его место.хорошо, этот код работает при первом вызове, но во втором вызове он вылетает и пишет:

*** glibc detected *** ./b: double free or corruption (top): 0x092ae138 ***  

Я не смог найти ответ на него, и я надеюсь, что вы поможете.
Это звонки отmain ()

BoardP p = CreateNewBoard(10,10);
PutBoardSquare(p,10,5,'X');
PutBoardSquare(p,5,10,'O');

Boolean PutBoardSquare(BoardP theBoard, int X, int Y, char val) {

    if (inBounds(X,Y,theBoard->_rows,theBoard->_cols)) {
        theBoard->_board[X * theBoard->_cols + Y] = val;
        return TRUE;
    }
    else {
        int newRows = (X>=theBoard->_rows) ? (2*X) : theBoard->_rows;
        int newCols = (Y>=theBoard->_cols) ? (2*Y) : theBoard->_cols;
        BoardP newBoard = CreateNewBoard(newCols,newRows);  //this creates a new Board with the new dimensions
        if (newBoard == NULL) {
            //ReportError(MEM_OUT);
            return FALSE;
        }
        else {
            copyData(theBoard,newBoard);
            freeBoardArray(&theBoard->_board[0]); //free old array
            theBoard->_board = newBoard->_board;  //old array point to new array
            FreeBoard(newBoard);  //free the temp copy THIS CAUSES THE PROBLEM  
            PutBoardSquare(theBoard,X,Y,val);//recursion, will be in bounds now
            return TRUE;
        }
    }
}

Это бесплатные функции:

void FreeBoard(BoardP board) {
    if (board != NULL) {
        printf("FREE 1\n");
        //free the board array:
        if (board->_board != NULL) {
            printf("FREE 2\n");
            freeBoardArray(&board->_board[0]);
            printf("FREE 3\n");
        }
        free(board);
    }
}

static void freeBoardArray(char * arrP) {
    free(arrP);   //**PROGRAM CRASH HERE**
}

Вот как я создаю новую доску:

BoardP CreateNewBoard(int width, int high) {
    BoardP board = (BoardP) malloc(sizeof(Board));
    if (board != NULL) {
        board->_board = allocateBoardArray(high,width);
        if ( board->_board == NULL) {
            FreeBoard(board);
            //TODO make file ReportError(MEM_OUT);
            return NULL;
        }
        initializeBoard(board,high,width,X_SIGN,SPACE);
        return board;
    }
    else {
        FreeBoard(board);
        //TODO make file ReportError(MEM_OUT);
        return NULL;
    }
}

static char* allocateBoardArray(int row, int col) {
    char* newBoard = (char*) malloc(row * col * sizeof(char));

    if (newBoard == NULL) {
        return NULL;
    }
    return newBoard;
}

это BoardP:

typedef struct Board* BoardP;

Ответы [ 4 ]

6 голосов
/ 28 августа 2010

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

theBoard->_board = newBoard->_board;

Теперь вы сохраняете ссылку на выделенный указатель, а затем освобождаете тот же самый указатель.

Пример кода:

char *foo()
{
char *ref1;
char *ref2;
ref1 = malloc(256);
ref2=ref1;// Holding reference to a pointer in another pointer
strcpy(ref1,"stackoverflow");
printf("%s %s",ref1,ref2); // This prints stackoverflow twice
free(ref1); // This is valid but you can access ref2 or ref1 after this point
return ref2; /// This will cause problems
}
1 голос
/ 28 августа 2010

Попробуйте это:

copyData(theBoard, newBoard);
/* swap the _board pointers */
char * b = theBoard->_board;
theBoard->_board = newBoard->_board;
newBoard->_board = b;
FreeBoard(newBoard);  /* cleanup the temp struct and the old array */
0 голосов
/ 28 августа 2010

Запуск этого кода в valgrind точно скажет вам, на какой строке вы: а) впервые освободили память и б) когда вы попытаетесь освободить его снова.

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

0 голосов
/ 28 августа 2010

Эта ошибка говорит о том, что вы пытаетесь освободить память, которая уже освобождена вами. То, что я подозреваю, вот этот блок кода

if (board != NULL) {
printf("FREE 1\n");
//free the board array:
if (board->_board != NULL) {
    printf("FREE 2\n");
    freeBoardArray(&board->_board[0]);
    printf("FREE 3\n");
}
free(board);

после освобождения части структуры freeBoardArray (& board -> _ board [0]); и затем вы освобождаете всю структуру free (board); и мне кажется, что это вызывает проблему. Почему вы передаете адрес указателя _board? Я написал код в той же строке кода, которая и вызывает проблему.

struct a{
    int * next;

}; int main () {

    struct a *aptr = (struct a *)malloc(sizeof(struct a));
    aptr->next=(int *)malloc(5*sizeof(int));
    free(&aptr->next);
    free(aptr);
    return 0;

}

этот код вызовет ту же проблему, что и вы. Теперь снова попробуйте этот код после удаления '&' из free (& aptr-> next); Statement.It будет работать нормально. Так что я думаю, у вас есть подсказка, где вы должны изменить.

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