GraphBLAS wrapper PhantomData invalid memory reference

Hey,

I'm new at rust but I've been coding for most of my life, I'm trying to write a wrapper against GraphBLAS C lib from SuiteSparse.

I was able to wrap a GrB_Matrix and create it and drop it successfully

However when I try adding a PhantomData to my struct to make it generic I get signal: 11, SIGSEGV: invalid memory reference

This happens when I try to call the C api in Drop

when I do the same but with an actual generic value instead of PhantomData it works.

Example with PhantomData failing

I feel the problem is not dropping everything correctly

Note that this

#[macro_use]
extern crate lazy_static;

lazy_static! {
    static ref TEST: u32 = {
        println!("init");
        10
    };
}

fn main() {
    let _ = TEST;
}

does not print anything. If you write let _ = *TEST instead of let _ = TEST, it will print something. This is because lazy_static just creates a new type for each variable with a Deref impl that initializes it an returns a reference to the actual type (in this case u32), but this means you actually have to dereference it to initialize it.

Thanks, that's true, I'll update that, sadly the error is still there.

this one works if I provide a value

pub struct SparseMatrix<T>{
mat: *mut GrB_Matrix,
phantom: T // FIXME: this sould work with a PhantomData but it doesn't
}

It's likely to be an issue that happens randomly depending on the mood of the compiler applying optimizations because of something being unsound. I don't think the PhantomData itself is the culprit.

What is the return value of GrB_Matrix_new? It can fail. How do the generated bindings look?

extern "C" {
pub fn GrB_Matrix_new(
A: *mut GrB_Matrix,
type_: GrB_Type,
nrows: GrB_Index,
ncols: GrB_Index,
) -> GrB_Info;
}

pub type GrB_Info = u32;
pub type GrB_Index = u64;

If I remove the GrB_Matrix_free all goes well but I don't get to free the allocated memory managed by GrB_Matrix

This is GrB_Matrix

#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct GB_Matrix_opaque {
    _unused: [u8; 0],
}
pub type GrB_Matrix = *mut GB_Matrix_opaque;

Please surround your code with three backtics

```
// your code goes here
```
1 Like

I recommend trying:

  1. Check the return value of GrB_Matrix_new. It should probably return GrB_SUCCESS.
  2. Initialize A to ptr::null_mut() instead. Try printing the pointer after the initialize call.
  3. Try blocking mode.

I tried using null_mut but it failed with GrB_NULL_POINTER

I really think the problem is calling free on something wrong, I added some other calls to get the number of rows for example so the ffi seems to work

impl<'a, T> SparseMatrix<'a, T> {
    pub fn new(size: (u64, u64)) -> SparseMatrix<'a, T>{

        let _ = *GRB; // make sure lib is init ?
        let mut A = MaybeUninit::<GrB_Matrix>::uninit();

        let (rows, cols) = size;
        unsafe {
            GrB_Matrix_new(A.as_mut_ptr() , GrB_BOOL, rows, cols);
        };

        let mat = A.as_mut_ptr();
        println!("MAT {:p}", mat);
        SparseMatrix{ mat: mat, _marker: PhantomData, }
    }

    pub fn rows(&mut self) -> u64 {
        let mut P = MaybeUninit::<u64>::uninit();

        unsafe {
            GrB_Matrix_nrows(P.as_mut_ptr(), *self.mat);
        }
        unsafe{P.assume_init()}
    }
}

:frowning: for some reason it now works

        let mat = A.as_mut_ptr();
        println!("MAT {:p}", mat);
        SparseMatrix{ mat: mat, _marker: PhantomData, }

why on earth would printing the pointer make it work

Finally settled for

pub struct SparseMatrix<T>{
    mat: *mut GrB_Matrix,
    _marker: PhantomData<*const T>
}

and this seems to work, thanks for the help