Skip to content

Valgrind thinks the slice's memory is leaked since no real pointer remains to it #2

Description

@federicomenaquintero

In librsvg we got this issue about a leak reported by Valgrind:

==6237== 40 bytes in 1 blocks are definitely lost in loss record 1,053 of 1,774
==6237==    at 0x483A7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==6237==    by 0x49F2BB6: alloc (alloc.rs:80)
==6237==    by 0x49F2BB6: alloc (alloc.rs:174)
==6237==    by 0x49F2BB6: allocate_in<selectors::parser::Component<rsvg_internals::css::Selector>,alloc::alloc::Global> (raw_vec.rs:152)
==6237==    by 0x49F2BB6: with_capacity_in<selectors::parser::Component<rsvg_internals::css::Selector>,alloc::alloc::Global> (raw_vec.rs:135)
==6237==    by 0x49F2BB6: with_capacity<selectors::parser::Component<rsvg_internals::css::Selector>> (raw_vec.rs:92)
==6237==    by 0x49F2BB6: with_capacity<selectors::parser::Component<rsvg_internals::css::Selector>> (vec.rs:358)
==6237==    by 0x49F2BB6: <alloc::vec::Vec<T> as alloc::vec::SpecExtend<T,I>>::from_iter (vec.rs:2073)
==6237==    by 0x4ADC6DF: from_iter<selectors::parser::Component<rsvg_internals::css::Selector>,smallvec::IntoIter<[selectors::parser::Component<rsvg_internals::css::Selector>; 2]>> (vec.rs:1981)
==6237==    by 0x4ADC6DF: collect<smallvec::IntoIter<[selectors::parser::Component<rsvg_internals::css::Selector>; 2]>,alloc::vec::Vec<selectors::parser::Component<rsvg_internals::css::Selector>>> (iterator.rs:1660)
==6237==    by 0x4ADC6DF: into_vec<[selectors::parser::Component<rsvg_internals::css::Selector>; 2]> (lib.rs:1073)
==6237==    by 0x4ADC6DF: parse_negation<rsvg_internals::css::RuleParser,rsvg_internals::css::Selector> (parser.rs:1987)
==6237==    by 0x4ADC6DF: selectors::parser::parse_functional_pseudo_class (parser.rs:2088)

Here, selectors is the selectors crate from Servo; it uses thin-slice for a few things.

From servo/components/selectors/parser.rs:

fn parse_negation<'i, 't, P, Impl>(
    parser: &P,
    input: &mut CssParser<'i, 't>,
) -> Result<Component<Impl>, ParseError<'i, P::Error>>
{
    ...
    Ok(Component::Negation(
        sequence.into_vec().into_boxed_slice().into(),
    ))
}

Component::Negation is a ThinBoxedSlice:

pub enum Component<Impl: SelectorImpl> {
    // ...
    Negation(ThinBoxedSlice<Component<Impl>>),
    // ...
}

I think Valgrind sees the malloc from the call to sequence.into_vec(), then it gets turned to a boxed slice, then to a ThinBoxedSlice. But since that erases the pointer from malloc, Valgrind thinks it's leaked.

So... this is not a real bug in thin-slice, just a bad interaction with Valgrind. I don't know if it's possible to have a suppression file for it.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions