2012-04-01 2 views
2

Это действительно начинающий вопрос, но я не пишу C, если (ERR, если) я могу избежать этого;)Использование библиотечных функций, которые возвращают массивы

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

Внутри жесткой петли Я использую функции MYSQL_FIELD * mysql_fetch_fields(...) и unsigned long * mysql_fetch_lengths(...).

Поскольку эти функции возвращают массивы, я предполагаю, что они будут использовать malloc() поэтому требуют, чтобы пользователь вызвать free() вручную, когда закончил с результатом? Я ожидал, что это будет задокументировано в руководстве, но это не так, поэтому я полагаю, что это одна из тех вещей, которые разработчики C просто делают инстинктивно: http://dev.mysql.com/doc/refman/5.0/en/mysql-fetch-fields.html

Любые указатели? (В смысле советы;))

Код в вопросе здесь: https://github.com/d11wtq/oedipus/blob/master/ext/oedipus/oedipus.c#L137-138

EDIT | Фу, теперь у меня есть сомнения. Документировано называть mysql_free_result() в результирующем наборе, который был передан mysql_fetch_fields(), поэтому, возможно, это просто возвращает указатель на то, что уже находится в куче, из этой структуры MYSQL_RES.

EDIT 2 | Извините за шум. Это действительно кажется, что эта информация просто вытащил из MYSQL_RES структуры, которая является аргументом mysql_fetch_fields(), и сама освободила позже, так что я, вероятно, хорошо:

typedef struct st_mysql_res { 
    my_ulonglong row_count; 
    MYSQL_FIELD *fields; 
    MYSQL_DATA *data; 
    MYSQL_ROWS *data_cursor; 
    unsigned long *lengths;    /* column lengths of current row */ 
    MYSQL   *handle;    /* for unbuffered reads */ 
    const struct st_mysql_methods *methods; 
    MYSQL_ROW  row;     /* If unbuffered read */ 
    MYSQL_ROW  current_row;   /* buffer to current row */ 
    MEM_ROOT  field_alloc; 
    unsigned int field_count, current_field; 
    my_bool  eof;     /* Used by mysql_fetch_row */ 
    /* mysql_stmt_close() had to cancel this result */ 
    my_bool  unbuffered_fetch_cancelled; 
    void *extension; 
} MYSQL_RES; 
+1

Вы не пишете C, если не можете избежать этого? Значит, вы пишете C только тогда, когда можете этого избежать? :) –

+0

Mind = blown (: - – d11wtq

+0

haha ​​«если я могу его избежать» или «если я не могу этого избежать» будет работать в вашем случае. Если бы только английский был таким же простым, как C, не так ли? –

ответ

4

Вам нужно позвонить mysql_free_result(result), где результат является результатом от mysql_fetch_fields. Разработчики C используются для этой парадигмы программирования, но нет никакой функции, которую вы вызываете, чтобы освободить что-то, выделенное в другой библиотеке. Каждая библиотека будет иметь функции, которые выделяют и возвращают что-то, а затем функцию для освобождения результатов выделения. Клиент не может освободить его самостоятельно с помощью free или delete, поскольку он может быть выделен на другой куче и может быть сложным объектом с несколькими выделениями внутри.

1

Ссылка API вы использовали до сих пор дает ответ: Вы должны освободить память из наборов результатов с помощью mysql_free_result() функции:

Освобождает память, выделенную для результирующего набора mysql_store_result(), mysql_use_result() , mysql_list_dbs() и т. Д. Когда вы делаете с помощью результирующего набора, вы должны освободить память, которую он использует, позвонив по телефону mysql_free_result().

Не пытайтесь получить доступ к набору результатов после его освобождения.

И да, программисты C довольно привыкли к API, которые предоставляют _free() процедуры для возвращаемых объектов. Это просто часть территории.

0

Функция mysql_store_result хранит весь результат запроса в куче и возвращает структуру, содержащую указатели на все данные. Такие функции, как mysql_fetch_row и mysql_fetch_fields, просто верните некоторые из этих данных.Функция mysql_free_result несет ответственность за освобождение всех данных результата, включая возвращаемые поля mysql_fetch_fields.

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

Смежные вопросы