how can i stop memory leaks in rust FFI?

251 Views Asked by At

I'm trying to create some bindings from a C library for rust with bindgen and everything was going well until I realized that my program was having memory leak problems

enter image description here

Thanks to heaptrack I was able to identify the function that was causing these memory leaks,

enter image description here

this function CP56Time2a_createFromMsTimestamp creates a timestamp to then be added to another structure (InformationObject) before being sent, when this structure is sent a method is called that frees the memory of the structure (InformationObject_destroy) and I guess also the memory of the timestamp, in the library there is no method to free the memory of the timestamp

How can I deallocate or free this memory? The resulting structure of the function is a pointer *mut sCP56Time2a

minimal example of what I'm doing:

use iec60870::bindings;
use std::ffi::CString;

pub struct CP56Time2a;

impl CP56Time2a {
    pub fn create() -> *mut bindings::sCP56Time2a {
        unsafe {
            bindings::CP56Time2a_createFromMsTimestamp(
                std::ptr::null_mut(),
                bindings::Hal_getTimeInMs(),
            )
        }
    }
}

pub struct Slave {
    inner: bindings::CS104_Slave,
}

impl Slave {
    pub fn new(addr: &str, port: i32) -> Self {
        let inner = unsafe {
            let inner = bindings::CS104_Slave_create(100, 100);
            let address = CString::new(addr).unwrap().as_c_str().to_owned();
            bindings::CS104_Slave_setLocalAddress(inner, address.as_ptr());
            bindings::CS104_Slave_setLocalPort(inner, port);
            bindings::CS104_Slave_setServerMode(inner, 1);

            inner
        };

        Self { inner }
    }
}

fn main() {
    unsafe {
        let slave = Slave::new("127.0.0.1", 2404);
        let param = bindings::CS104_Slave_getAppLayerParameters(slave.inner);

        let asdu = bindings::CS101_ASDU_create(param, false, 3, 0, 1, false, false);
        let timestamp = CP56Time2a::create();

        let me = bindings::MeasuredValueScaledWithCP56Time2a_create(
            std::ptr::null_mut(),
            1000,
            20,
            0,
            timestamp,
        );

        bindings::CS101_ASDU_addInformationObject(asdu, me as bindings::InformationObject);
        // send asdu
        bindings::InformationObject_destroy(me as bindings::InformationObject);
        bindings::CS101_ASDU_destroy(asdu);
    }
}
0

There are 0 best solutions below