简体   繁体   中英

Suspicious memory leak when using getopt lib in MySQL?

内存使用率和线程使用率监视器

I am posting this post on behalf of my college.

He found a suspicious memory leak when using the handle_option (MySQL getopt lib) to read config file (/etc/my.cnf)

He execute the Source code below after malloc host_name, user name:

char* host_name;
char* user_name;

struct my_option mysql_confgs[] = 
{
  {"host", "h", "MySQL Server", (uchar**) & host_name, NULL, NULL, GET_STR, 
REQUIRED_ARG, 0,0,0,0,0,0},
    {"user", "u", "userID", "h",(uchar**) & user_name, NULL, NULL, GET_STR, 
REQUIRED_ARG, 0,0,0,0,0,0}
}

handle_options(&argc, &argv, mysql_configs, aux_config_reader);

He mention about the method above is using Error(Segment) instead of using free(host_name) and free(user_name)? So this is the possible reason of causing memory leakage?

Well.. I have zero basic on MySQL, so I might not able to delivery 100% of the problem description. So, feel free to query on this and I will update the details of problem descriptions as per the query.

My college is having language barrier so I am posting on behalf of him.

Valgrind Report:

480 bytes in 1 blocks are possibly lost in loss record 26 of 43
at 0x4A068FE: malloc (vg_replace_malloc.c:270)
by 0x33E4E293C1: my_malloc (in /usr/lib64/mysql/libmysqlclient.so.16.0.0)
by 0x33E4E2C974: alloc_root (in /usr/lib64/mysql/libmysqlclient.so.16.0.0)
by 0x33E4E2E620: ??? (in /usr/lib64/mysql/libmysqlclient.so.16.0.0)
by 0x33E4E2F838: my_load_defaults (in /usr/lib64/mysql/libmysqlclient.so.16.0.0)
by 0x408BF1: MS_MYSQL_init (MS_MYSQL_O.h:109)
by 0x438A39: main_proc (AccLab.c:221)
by 0x437F8A: main (AccLab.c:67)

75,840 bytes in 158 blocks are definitely lost in loss record 41 of 43
at 0x4A068FE: malloc (vg_replace_malloc.c:270)
by 0x33E4E293C1: my_malloc (in /usr/lib64/mysql/libmysqlclient.so.16.0.0)
by 0x33E4E2C974: alloc_root (in /usr/lib64/mysql/libmysqlclient.so.16.0.0)
by 0x33E4E2E620: ??? (in /usr/lib64/mysql/libmysqlclient.so.16.0.0)
by 0x33E4E2F838: my_load_defaults (in /usr/lib64/mysql/libmysqlclient.so.16.0.0)
by 0x408BF1: MS_MYSQL_init (MS_MYSQL_O.h:109)
by 0x438A39: main_proc (AccLab.c:221)
by 0x437F8A: main (AccLab.c:67)

LEAK SUMMARY:

definitely lost: 75,840 bytes in 158 blocks
indirectly lost: 0 bytes in 0 blocks
possibly lost: 2,304 bytes in 7 blocks
still reachable: 9,675,408 bytes in 2,387 blocks
suppressed: 0 bytes in 0 blocks
Reachable blocks (those to which a pointer was found) are not shown.
To see them, rerun with: --leak-check=full --show-reachable=yes

For counts of detected and suppressed errors, rerun with: -v
ERROR SUMMARY: 8 errors from 8 contexts (suppressed: 4 from 4)

Put printf("user_name: %p; host_name: %p\\n", (void *) user_name, (void *) host_name); before and after the call to handle_options and run your code. Do the additional two lines printed as a result differ from each other? If so, your diagnosis is correct and user_name and host_name are changed by handle_options, and perhaps using a malloc'd pointer is unsuitable for this function.

If not, your diagnosis is incorrect and the memory leak lies elsewhere. You'd want to look at the source code for MS_MYSQL_init, main_proc and main, in that order, which are the three functions listed by valgrind from your project. Let me know if you need my help...

I'd say the combination of allocating memory to the pointer my_option.value is pointing to along with the use of GET_STR is leading to leaking what had been allocated to my_option.value , as GET_PTR initalises what my_option.value is pointing to, to point right to somewhere into what had been passed as argv to handle_options , without freeing what the value my_option.value is pointing, previously pointed to.

To get around this, either do not allocate any memory to what my_option.value is pointing to prior to passing it to handle_options or allocate it using my_alloc() and use GET_PTR_ALLOC as value type, as GET_PTR_ALLOC implies a call to my_free() on what my_option.value is pointing to prior to re-initialising what it is pointing to.


Just out of curiosity: What is uchar , and why do you cast to uchar ** and not to void * , the type of my_option.value ?


Also this

"user", "u", "userID", "h",(uchar**) & user_name ...

should read

"user", "u", "userID", (uchar**) & user_name ...

shouldn't it?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM