Управление памятью и перевыделение

Вложенный запрос может сделать задание.

SELECT author_last_name, dewey_number, NumOccurrences
FROM author INNER JOIN
     ( SELECT author_id, dewey_number,  COUNT(dewey_number) AS NumOccurrences
        FROM book
        GROUP BY author_id, dewey_number
        HAVING ( COUNT(dewey_number) > 1 ) ) AS duplicates
ON author.id = duplicates.author_id

(я не знаю - ли это самый быстрый способ достигнуть того, что Вы хотите.)

Обновление: Здесь мои данные

SELECT * FROM author;
 id | author_last_name 
----+------------------
  1 | Fowler
  2 | Knuth
  3 | Lang

SELECT * FROM book;
 id | author_id | dewey_number |         title          
----+-----------+--------------+------------------------
  1 |         1 |          600 | Refactoring
  2 |         1 |          600 | Refactoring
  3 |         1 |          600 | Analysis Patterns
  4 |         2 |          600 | TAOCP vol. 1
  5 |         2 |          600 | TAOCP vol. 1
  6 |         2 |          600 | TAOCP vol. 2
  7 |         3 |          500 | Algebra
  8 |         3 |          500 | Undergraduate Analysis
  9 |         1 |          600 | Refactoring
 10 |         2 |          500 | Concrete Mathematics
 11 |         2 |          500 | Concrete Mathematics
 12 |         2 |          500 | Concrete Mathematics

И здесь результат вышеупомянутого запроса:

 author_last_name | dewey_number | numoccurrences 
------------------+--------------+----------------
 Fowler           |          600 |              4
 Knuth            |          600 |              3
 Knuth            |          500 |              3
 Lang             |          500 |              2
8
задан Sinan Ünür 23 October 2009 в 14:35
поделиться

6 ответов

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

11
ответ дан 5 December 2019 в 10:04
поделиться

Если realloc () терпит неудачу, она возвращает ноль и исходный блок не освобождается . Эта строка:

Hash->Columns = (HASH_COLUMN *)realloc(Hash->Columns, Hash->nColumns * sizeof(HASH_COLUMN)); // line 243

не проверяет возвращаемое значение. Поэтому, если realloc () не работает, в Hash-> Columns записывается null, и происходит утечка исходного блока.

2
ответ дан 5 December 2019 в 10:04
поделиться

Не уверен, что это проблема, но это потенциально проблематично. Из справочной страницы для realloc () :

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

После успешного завершения с размером, отличным от 0, realloc () возвращает указатель на (возможно, перемещенный ) выделенное пространство. Если размер равен 0, возвращается либо нулевой указатель, либо уникальный указатель, который может быть успешно передан в free () . Если доступной памяти недостаточно, realloc () возвращает нулевой указатель и устанавливает для errno значение [ENOMEM].

Что произойдет, если недостаточно места для расширенного объекта, старый объект по-прежнему действителен и не освобожден, но realloc () возвращает NULL . Поэтому вам следует сохранить результат, возвращаемый функцией realloc () , в отдельной переменной, проверьте эту переменную на NULL , и если это не так, присвойте ее Hash-> Columns .

1
ответ дан 5 December 2019 в 10:04
поделиться

Ага - комментарий асвейкау:

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

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

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

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

1
ответ дан 5 December 2019 в 10:04
поделиться

Valgrind не говорит, что утечка происходит в строке realloc - он говорит, что память, выделенная этой строкой realloc , является память, которая, в конце концов, утекает. Однако Valgrind не знает, где - он просто знает, что у вас больше нет ссылки на эту память, поэтому было бы невозможно освободить ее. (OP может это знать, но очевидно, что многие из ответчиков этого не знают!)

Короче говоря, код, который вы вставили, не вызывает проблемы (хотя проблема, которую поднимает Майкл Берр, определенно реальна, но поскольку вы даже не проверяете NULL , возвращенное из realloc ...)

Где-то в вашем коде должно быть свободное (Hash-> Столбцы) , которого сейчас нет. Найдите это место - вероятно, незадолго до освобождения самого хеша и добавьте его.

2
ответ дан 5 December 2019 в 10:04
поделиться

В Mac OS X и FreeBSD et al. у вас также есть функция reallocf ():

man 3 malloc | less -p reallocf 
... 
     The reallocf() function is identical to the realloc() function, except
 that it will free the passed pointer when the requested memory cannot be
 allocated.  This is a FreeBSD specific API designed to ease the problems
 with traditional coding styles for realloc causing memory leaks in
 libraries.
0
ответ дан 5 December 2019 в 10:04
поделиться