Rust ffi problem


pub struct MysqlOption {
    pub host:     *const c_char,
    pub port:     *const c_short,
    pub username: *const c_char,
    pub password: *const c_char,
    pub dbname:   *const c_char,

pub unsafe extern fn init_mysql_config(config: *mut MysqlOption) {
    let raw_host = CString::from_raw((*config).host as *mut c_char);

    println!("host: {}", raw_host.to_str().unwrap());
    println!("next drop");


struct _mysql_opt {
    char *host;
    short port;
    char *username;
    char *password;
    char *dbname;

typedef struct _mysql_opt mysql_opt;

void init_mysql_config(mysql_opt *opt);


#include <stdio.h>
#include <stdlib.h>

#include "rust_mysql.h"

main(int argc, char **argv) {
    mysql_opt opt; = "";
    opt.port = 3306;
    opt.username = "root";
    opt.password = NULL;
    opt.dbname = "asd";


when init_mysql_config lifetime end, i got a exception!

next drop
test(30436,0x7fff77a24000) malloc: *** error for object 0x10b7a2f68: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6

how to fix that. thanks;


You’re using CString::from_raw. From the documentation ( ):

Retakes ownership of a CString that was transferred to C.

The only appropriate argument is a pointer obtained by calling into_raw. The length of the string will be recalculated using the pointer.

The “takes ownership” part tells you that the CString object will, when dropped, free() the passed string; but in your example code, host is a string literal (""). Since the string is not in the heap, it doesn’t make sense to use CString; instead, use CStr, which is intended for strings that are owned by the caller.

Something like this should work (untested):

let raw_host = CStr::from_ptr((*config).host);
println!(“host: {}”, raw_host.to_str().unwrap());


wow! thanks.