3

This is a really novice question, but I don't write C unless (err, if) I can avoid it ;)

I've written a small extension to ruby that needed to interface with libmysql. It works as expected, but now I'm in some doubt as to whether two lines of code a resulting in a possible memory leak.

Inside a tight loop I'm using functions MYSQL_FIELD * mysql_fetch_fields( ... ) and unsigned long * mysql_fetch_lengths( ... ).

Since these functions return arrays, I assume they would use malloc() therefore require the user to call free() manually when finished with the result? I expected this to be documented in the manual, but it's not, so I assume this is one of those things C developers just do instinctively: http://dev.mysql.com/doc/refman/5.0/en/mysql-fetch-fields.html

Any pointers? (in the advice sense ;))

The code in question is here: https://github.com/d11wtq/oedipus/blob/master/ext/oedipus/oedipus.c#L137-138

EDIT | Ugh, now I have a doubt. It is documented to call mysql_free_result() on the result set, which was passed to mysql_fetch_fields(), so perhaps this is just returning a pointer to something that's already on the heap, from that MYSQL_RES struct.

EDIT 2 | Sorry for the noise. It does appear that this information is just pulled from the MYSQL_RES struct which is an argument to mysql_fetch_fields(), and is itself freed later, so I'm probably fine:

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;
2
  • 1
    You don't write C unless you can avoid it? So you write C only when you can avoid it? :) Commented Apr 1, 2012 at 22:56
  • haha "if I can avoid it" or "unless I can't avoid it" would work in your case. If only English were as simple as C, right? Commented Apr 1, 2012 at 23:02

3 Answers 3

4

You need to call mysql_free_result(result) where result is the result of mysql_fetch_fields. C developers are used to this programming paradigm, but there is no one function you call to free something allocated in another library. Each library will have functions that allocate and return something, then a function to free the results of the allocation. The client can't free it itself with free or delete as it may be allocated on a different heap, and may be a complex object with multiple allocations inside.

Sign up to request clarification or add additional context in comments.

Comments

1

The API reference you've used so far provides the answer: You need to free the memory from result sets using the mysql_free_result() function:

Frees the memory allocated for a result set by mysql_store_result(), mysql_use_result(), mysql_list_dbs(), and so forth. When you are done with a result set, you must free the memory it uses by calling mysql_free_result().

Do not attempt to access a result set after freeing it.

And yes, C programmers are quite used to APIs that provide _free() routines for returned objects. It's just part of the territory.

Comments

1

The function mysql_store_result store the whole result of the query in the heap, and returns a struct that contain pointers to all the data. Functions like mysql_fetch_row and mysql_fetch_fields just return some of this data. The function mysql_free_result is responsible to free the whole result data, including the fields mysql_fetch_fields returned.

So, you only need to call mysql_free_result after you use the data, and it will do the work.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.