Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I'm curious about hot takes on Rust adoption in the Linux kernel. I saw some talk from Linux a few months back where he basically conceding needing something like Rust to get all the Cool New Kids to start doing kernel development, and Google has some big push going to use it in the kernel. I don't really know how far along it is and if it's consumable yet. I'm trying to make a call on if/when we might want to transition into writing and working with Rust code. I particularly wish I could easily have unit test coverage of a lot of the code I'm running in kernel space.

Adbot
ADBOT LOVES YOU

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
Can somebody give an impression on the error handling in Rust for an outsider? I was following along with what I was reading at https://doc.rust-lang.org/book until I got to error management. It looks like it's trying to square the circle in systems programming with putting error management next to the offending statement while still having something like exceptions. How does your thinking change in Rust when using this kind of error management?

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
How do I convert a String in Rust to go into a C function call requiring wchar_t*? For what it's worth, the function involved just sees English alphanumeric characters, but I think it was made wchar_t* for futureproofing. I don't have the leeway to change the API.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
The library's fine. I don't really know what's out there. Now, is there a way to turn a *const c_char into a w_char by going through a widestring? I thought I'd try starting from CStr in an unsafe block but I can't seem to work it from there.

Edit: Ehh I think I found something but wow this is pretty goofy stuff to do! My Rust code is the meat in a C/C++ sandwich so I'm getting hit on both sides.

Edit Edit: No I did not find something. I can't seem to find an incantation that takes me from a C char* coming in to wchar_t* going out. I can dance around a pile of conversions all day but never seem to get the two ends together. My default path here is to just grind the widestring APIs and sketch on paper any possible path.

Rocko Bonaparte fucked around with this message at 19:30 on May 27, 2022

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I was close!

I was using WideCString::from instead of WideCString::from_str, and I wasn't using the into_raw() conversion. I would not have recognized from into_raw()'s signature that it produces something compatible with wchar_t*. I guess the UChar type is part of widestring and mates with the u32 type that wchar_t is in my project.

Holy gently caress. Well, I asked for it haha.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I'm specifically on Linux but I'm trying not to use the specifically sized stuff anyways. It's just that the compiler likes to throw u32 in my face.

I've got another nasty one. I have this type in C:
code:
const wchar_t* const * const keys
It was automatically wrapped like this:
code:
keys: *const *const wchar_t,
[code]

I'm not really good on my const in Rust yet so I really just don't have any idea how I'd prepare this. I have to declare from scratch and am not working with an existing construct. I tried:

[code]
    let values: Vec<*const u32> = vec![w_json_data.into_raw()];
....
(..., &values as *const *const u32, ...)
And of course "casting `&Vec<*const u32>` as `*const *const u32` is invalid." I'm not surprised but I don't know how I'd do it instead. I really jumped into the deep end putting myself in between getting called by C and then calling C lol.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
As a general rule, should I be hunting for as_ptr and into_raw_parts functions when I hit a bind like that? I'm guess it's standardized in a trait or something.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
Thanks for all the little tips there. That gives me some street smarts I wouldn't be finding normally in some O'Reilly book.

I kind of picked for work an example of having C calling Rust calling C on the assumption it would really suck, but I expect we'd have to do a lot of this if we started to stir Rust into our work. It's been a great way of quickly ending the Honeymoon period and looking at the language more objectively. It's still holding up and I do intend to keep on using it.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
With FFI and everything, does a CString directly correspond to a char*? When I ran cbindgen, it used const char* for CString in the function bindings, but it used CString for a struct declaration. I tried to declare that as char*, which I think severely angered it. I get a segfault when I try to assign to one of the CString fields that I declare in the header as char*.

Edit: I guess I should use *mut c_char for the struct fields instead of CString and into_raw() to assign to them. Fun times!

Rocko Bonaparte fucked around with this message at 06:41 on Jun 2, 2022

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
Yeah FFI has been a much more surprising pain in the rear end compared to other language interoperations I've used before. However, I think half of my problems have actually just been with strings; they wear me out before I have to deal with the FFI stuff.

I keep getting ahead of where I am in Programming Rust. I stopped after basic syntax originally and then got my rear end handed to me when I got some functions returning Result<>. I think the next chapter was going to be strings in detail and that should hopefully clear some stuff up. It's a lot easier to pay attention to that stuff after it's hit me in the face a few times.

I was originally just going to wait until we have an opportunity for a new standalone application in order to try Rust, but I just kept seeing stuff about people integrating Rust with Python, Rust with userspace C++ stuff, and then Rust with kernelspace C stuff. The Python and kernelspace stuff matter to me in my job. So I just decided, "gently caress it, let's just see what it's like to integrate with it." Hahaha it's not so good that way.

Counterpoint: It's also not fair to compare an interoperating Rust function to its raw C equivalent because the Rust version is doing what the function has to do and it's converting to/from C. Yes, that's a hint that I should have a layer doing the translation and then a "pure" layer underneath. Anyways, it's shown me how difficult it would be to recommend this at a wider level in my team/organization if it has to be done with an existing C/C++ project.

Speaking of C: Is there anything I can particularly do to ensure I can bind with ANSI C code? The cbindgen is technically generating C++, but we have some code that is pure ANSI C, and then there's trying to do kernel-level code with it some day. For that, I figured I'd find what's being said out there about that ongoing project in the kernel, but I thought I'd ask here too.

Rocko Bonaparte fucked around with this message at 20:59 on Jun 2, 2022

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
Do any of you debug Rust code being called from C applications? I am trying to figure out if I can do this with clion.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I guess I'll just try to twist clion's arm to launch the test C binary and step down into the Rust code from there. It wasn't looking straightforward so I figured I'd ask before I broke my brains on it.

So next one: What should my weapon of choice be if I'm trying to expose both C bindings and Python bindings? I could just use ctypes and wrap the C calls, but I'd be creating a serial dependency chain; I anticipate the Python bindings unwittingly falling apart if I end up changing something in the Rust side. I'd rather present both the C and the Python bindings from the Rust code itself so they can change and rebuild with the Rust code changes directly.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
It looks like there's a cpython crate I can just use and since I'm pretty cozy with CPython stuff that I might as well just use it.

Something that might be more interesting: I wanted to do some paranoia one some of these unwraps() I was using on various text types in case there were some zeroes in the stream. I don't think they'd necessarily hit in all cases ever, but I tried to cover them just to be thorough and not just have all these unwrap calls running naked around the code. Now they're tucked in helpers in a way that they should never actually hit. The problem is that these functions are oh-so-similar yet I have to write a different one for each of the types. Can this all just be done better? Can I consolidate this?

(note I'm stuck with Rust 2018)

code:
fn make_cstring_from_str(in_str: &str) -> CString {
    let remapped: String = in_str.chars()
        .map(|x| match x {
            '\u{0}' => ' ',
            _ => x
        }).collect();

    CString::new(remapped).unwrap()
}

fn make_cstring_from_string(in_str: String) -> CString {
    let remapped: String = in_str.chars()
        .map(|x| match x {
            '\u{0}' => ' ',
            _ => x
        }).collect();

    CString::new(remapped).unwrap()
}

fn make_cstring_from_u8(in_ar: &[u8]) -> CString {
    let remapped: String = in_ar.to_vec().iter()
        .map(|x| match x {
            0 => ' ',
            _ => *x as char
        }).collect();

    CString::new(remapped).unwrap()
}

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
Yeah I saw what the error type was telling me and decided I'd want to just replace the characters if I got a surprise 0.

I haven't run enough Rust code to be certain of how I'd get bit by stuff like this, but one of the conversions I do will come from process stdout and that's been a huge bag of bear traps for me in other worlds. I'm using some of that output to create a hash and I'm fine with soldiering on if I get a surprise zero.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
Are there any mechanisms in place for standard crates from crates.io to independently download source and build them? We'd like to incorporate Rust but I have a corporate requirement to independently build source and run some security scanning in between.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
So that's going to be an ongoing thing. I found out about Software Build of Materials at the US Open Source Summit and supply chain security so I suspect this kind of thing is going to become much easier soon.

A new thing: I'm trying to do a command-line utility and I'm doing command line parsing. I picked up the clap crate and I'm surprised with a lot of the logic I have to write. A particular situation is subcommands ie the "pull" in "git pull." It looks like I have to do a conditional to find if each command was set--or perhaps I should say I have to do a match block. I've seen implementations in other languages just use callbacks for that kind of thing. Is that available in clap or some other command-line parsing library in the Rust ecosystem?

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
It looks like Args had an action field associated with them and that made we think I could trigger code on arguments as well as subcommands, but subcommands did not have an action field. I am guessing the Arg action is just a more advanced routine you can insert to process the input (I guess like Python's argparse?)

I was editing some code in the middle of my file and got plagued by this semi-classic:
code:
error: cannot satisfy dependencies so `std` only shows up once
  |
  = help: having upstream crates all available in one format will likely make this go away
My project.toml is targeting dylib. I see a recommendation to use -C prefer-dynamic with rustc, but what about at the project level? I'm trying to build with cargo. I'm also surprised I got whacked by this now. I have lib and bin paths defined, and was working on both and running the resulting application multiple times before this started happening. It kept on happening even after cleaning the project.

Edit: I tried to add this to my cargo.toml and it didn't make a difference:
code:
[build]
rustflags = ["-C", "prefer-dynamic"]
Edit, what the gently caress I changed my lib type from dylib to cdylib and it was happy.

Rocko Bonaparte fucked around with this message at 23:34 on Jul 14, 2022

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I got more build goofiness. I am betting I can't really get any help unless I posted literally everything and I can't really do that.

I have a src/bin/application.rs and a src/lib/lib.rs file. The lib.rs file has some FFI references to a C library. I can see in the build process that it builds correctly and includes the library. However, my application.rs immediately started to fail with missing references to that library in lib.rs the moment it started making calls to the functions in lib.rs that are using them.

If I run cargo build --verbose, I can see that application.rs is not being build with the library reference I need, so I'm not surprised it's missing it. The reference is in my build.rs. It's being set with rustc-link-lib. The lib.rs file seems to get it. What I gather from documentation is that this is supposed too only be set for stuff in a lib folder and not for a bin folder. So I guess the build system thinks its doing what it thinks it should do, but what am I supposed to do with my application calling into lib.rs?

I guess my problem is that lib.rs's functions must be getting inlined or something? How would I properly instead set the application to invoke stuff out of lib? I am import my lib code using:

code:
#[path = "../lib/lib.rs"] mod lib;
So I think I am basically inlining it. So what should I be doing instead?

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I'll post better details tomorrow. I managed to get it to build after some hacking. There is still a problem of the binary build ignoring rustc-link-lib; I had to explicitly set the -l flag in the cargo.toml in order for the linkage to the external library to stick. That's still a sore point for me. The other issues had to do with how I was organizing files and folders. I think the lesson learned so far is that I can't do that willy-nilly. There are some hidden assumptions for one, and I don't know all the details on how it works even in general without the assumptions. That's my problem.

I guess I should say that the next chapter I had to read in the Programming Rust book was about modules hahaha.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
Okay I'll post more here. This isn't a call to any kind of action or request of advice necessarily but me venting about stomping on, like, every rake that the module and build system has.

I had originally structured my project something like this:
src/
src/lib/
src/lib/lib.rs
src/bin/
src/bin/
src/bin/mainapp.rs
build.rs
Cargo.toml
[/code]

I wound up with:
code:
src/
src/lib.rs
src/mainapp.rs
build.rs
Cargo.toml
In the original structure, I couldn't figure out how to get mainapp.rs to find code from lib.rs without that #[path = butt] stuff at the top of the file. I still don't know how I would have done it. So I ended up just having the file cohabitate. There were additional problems. I didn't wrap lib.rs's code in a pub mod declaration to wrap it up in a module and namespace or whatever Rust calls it. So I was pretty much doomed from the start. Like, maybe I should just try it again now that I have one valid solution, but maybe I should just read the chapter on modules first.

What I couldn't fix without a ham-fisted solution was linking mainapp's binary output with an external C-based library. In my build.rs, I had added a cargo:rustc-link-lib println for it and that was working great for the library that lib.rs created. When it came time to link the console application from mainapp.rs, cargo wouldn't bother to add that library to the rustc command line. I then saw in the documentation that cargo:rustc-link-lib by design only applies to library builds and not for binary builds. I ended up just having to add a cargo:rustc-link-arg line specifically adding the -l flag for it in my build.rs. Not impressed.

Question: Why do I use [lib] for libraries in Cargo.toml but have to use [[bin]] for binaries?

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I had changed from hardcoding the path in the command-line application. This is what I'm using now:

code:
mod lib;

use std::borrow::BorrowMut;
use std::mem::MaybeUninit;
use clap::{Arg, App, SubCommand, Subcommand};

use crate::lib::lib as l;
The file tree was:
src/lib.rs
src/command-line.rs (not the real name)

lib.rs is wrapped in "pub mod lib" I feel kind of stupid having lib::lib and intend to change it but just decided to show you the sausage currently being made.

Is this just dumping the raw source for lib in my command-line application?

Edit: Closing that code tag.

Rocko Bonaparte fucked around with this message at 18:44 on Sep 20, 2022

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I blew quite a bit of time trying to invoke BufReader::lines() today. It was because I had neglected to import std::io::BufRead. I don't use BufRead directly but I guess that adds appropriate traits to use BufReader::lines on files. I got lucky with IRC and cross-checking examples online in this case, but how could I anticipate I'm neglecting something like that in the future?

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I just commented out the the BufRead import to see and yeah, I guess I do see that in the CLion output. The formatting was a little goofy though. I guess the moral of the story is to fully scour that output (surprise, surprise).

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

ploots posted:

There are a couple of competing approaches: the rust HAL people do things one way, Ferrous Systems have their own way of doing things, the Oxide people have a different approach. They’re all kind of incompatible.

Not knowing any of them, do they all ultimately try to put some layer up so you don't have to put unsafe blocks everywhere?

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
Have any of you tried to make Debian packages of Rust code? There's cargo-deb, which assumes you are going to build through cargo and hit the Internet to resolve everything along the way. Alternately, there's debcargo-conf, which assumes you're pulling do public stuff in Rust's repository for creating Debian packages. What I have is a corporate-internal project using our own internal build system that expects you to get all your dependencies squared away up-front.

The problem with this is I have to express all my dependencies as Debian packages, and these packages themselves have inconsistent sub-dependencies. So I have to bumble through layers of build errors to resolve all the dependencies. Is there at least some way with cargo where I can tell all the subdependencies I'm using normally so I can get all these listed one the first try?

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

kujeger posted:

Sounds like cargo vendor would be helpful

I never actually posted my reply but that lets me revise. The vendor command recursively gives me everything which wasn't what I wanted. What I was hoping that I could get the Debian names of everything I have to put in for a Debian package of my program. That should be a 1:1 translation of my Cargo.toml build dependencies but I kept getting snagged with subdependencies. That is, I needed error-chain, but I'd get whacked for missing the backtrace crate, for example.

I was told a solution from somebody on #debian-rust and it's probably worth knowing for somebody here. If you don't actually have specific features you are requesting from the dependency, you should use "default" for the Debian package in the package's build dependencies. That should resolve the subdependencies. So my Debian control file should not list a dependency for error-chain as librust-error-chain-dev, but instead as librust-error-chain+default-dev. I haven't verified this yet because I need to set up a new, reusable schroot for build testing.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I'm trying to figure out the local IP address on a Linux system with only creates in Debian Bullseye being available to me. It has sysinfo, but a version that only gives the device names and byte transfer sizes; it doesn't have the IP addresses. Is there something else?

This is harder problem that I first thought when I staggered into it. I have multiple interfaces and have to do some guesswork on which one is the real one. What I figured I'd do is look at them all, determine which one has the most bytes sent and received, and omit anything starting with 127 or 192. I'm not even getting into IPv6 stuff.

Parsing ifconfig is possible but I've had it drilled into me that output is not standardized, so I can expect surprises. This is leaving me with using "ip --json address show" and then cross referencing /sys/class/net/[interface]/statistics/tx_bytes and rx_bytes to get the traffic. At least I get to use JSON instead of trying to parse the ip command, I guess.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
Yeah that's a good command right there. Thanks.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
After an absence, I'm back to fuss over the square pegs and round holes I have to deal with in wide strings.

I have this:

code:
let values: Vec<*const u32> = vec![w_json_data.into_raw(),];   // w)json_data is widestring::WideCString
I needed that to pass wchar_t** to something, which is done with values.as_ptr()

The problem now is that element is raw and I need to reclaim it with from_raw(), but I can't figure out how to iterate it back from *const u32. Does anybody know the casting?

In this case, I can actually skirt around this because I can just do the raw cast outside the Vec declaration and then free it there. The problem is I particularly run into issues right here with wchar_t** conversion to_from so I just wanted to ask anyways for later.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
TBH I don't really know either. I think it's doing UTF-32 by default for WideCString. The compiler insists that into_raw() produces a *mut u32. Heck, I was thinking about that earlier:

code:
        let raw_json_data = w_json_data.into_raw();

        let values: Vec<*const u16> = vec![raw_json_data,];
code:
error[E0308]: mismatched types
   --> src/lib.rs:564:44
    |
564 |         let values: Vec<*const u16> = vec![raw_json_data,];
    |                                            ^^^^^^^^^^^^^ expected `u16`, found `u32`
    |
    = note: expected raw pointer `*const u16`
               found raw pointer `*mut u32`

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

Jabor posted:

Why are you using a Vec? Can't you just create your double-pointer by using & on the raw pointer?

I don't remember why particularly but I just remember crashing and burning after trying anything else. It has been a while so maybe I can work it out correctly if I try again fresh. The function I am calling is just taking wchar_t** and I am only giving it one element anyways.

Edit: Update The function I'm calling is from C and my bindings.rs has a signature of *const *const wchar_t. The variable I'm starting with is *mut WideChar. I can't seem to make the cast (it gets mad turning mut into const in particular). How do I make that cast without using a Vec as an intermediary?

Rocko Bonaparte fucked around with this message at 19:05 on Jan 18, 2023

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
Separate topic: is there a mocking tool in Rust with the same power as the mock library in Python? That library lets you call out replacements for individual function calls that are layers within code blocks that are otherwise invisible.

Yes, I have some issues dogmatically with that mocking method, but I would rather not totally refactor this trash code (as you have probably assumed by my posts) with all the interfaces I need to have non-system calls for testing.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I'm really shitposting about Rust today!

I figured out how to cast that double pointer without needing a Vec:
code:
        let keys: *const *const WideChar = &(raw_bridged_data_str as *const WideChar);
Easy peazy, right?

I got another problem: Some of my wide strings are leaking, but valgrind is only showing symbols into widestring itself. I have debug symbols in my library and application so I don't know what the problem is. Is there something special I have to do? For what it's worth, I got valgrind from source (3.21.0.GIT) since I saw some complaints about older versions with Rust binaries--something to do with the static compilation. It didn't make any difference. Some of the stuff it originally reported definitely came from my source. I had a few into_raw() calls that needed from_raw() calls to reclaim the memory, and the associated output disappeared from subsequent runs after fixing it. So it's not like these leaks originate literally in the widestring source.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I don't think that cast is the specific problem. The WideChar type is u32 but I'm just using the proper name for the platform. The character size isn't getting screwed with. At any rate, I didn't get a new leak from making that casting change. They're coming from some from_str() and clone() calls in more numbers than I have than that cast. I guess that's implying that yeah, I could have still screwed up, but I'm screwing up elsewhere too for unrelated reasons. I wish it would just tell me at what file and line number since it's at least able to see it up to the entrance into the widestring source each time.

I was just posting the cast because it looks like I figured out how to declare the cast without, say, putting it into a Vec first and giving the C call a raw pointer to its contents.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
All my output looks fine, and I've been printing out the strings I keep or otherwise transmitting them over a network using another library. My main concern is actually a crash that seems to be coming in OpenSSL cleanup from that other library (written in C++ with C bindings). Leaks aren't going to solve a double free, but I am trying to clean them up because I've seen that affect where a crash ultimately happens due to removing potential time bombs.

Getting into more details, I take the *const c_char I get from the parent C code, and use CStr::from_ptr() to wrap it. I immediately then copy it to a widened version using to_string_lossy, cleaning out characters out of range, then converting it to a WideCString using from_str(). That should be making a copy.

We can delve into that and look over things with a magnifying glass (though I can't post all the code) but I'd probably get a lot closer if valgrind would just tell me exactly where I blew it and leaked. Since I'm coming in after the fact, I have something like 700 lines of code that could be suspect at any point. I suppose if I were running valgrind as I went, I could have caught these with the vague output I got, but I didn't. :(

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I mean if I'm really gunning for it and I just can't get valgrind to print everything, I think I could set breakpoints at the reported points in the stack, find an input matching the rough size, and be pretty confident I'm at the scene of the crime. I also have some ways of running parts of the code in isolation; I don't have full unit testing (see my mock question) but I do have a utility that hits subsets of most of the code.

Some of the sizes are conspicious. Nothing is just, like, 1 byte. However, some of the sizes are, like 1700 kB and that smells like my JSON message. There's only a few places that could go wrong. So I can probably walk through it and see if I am hitting the offending areas there. One of them is that helper to making a WideCString from &CStr. There's a Cow<> in there and I see a ~1700kB clone not getting freed so my nostrils smell a problem right there.

All of that is still about being clever since I can't get it the straighforward way, which I was just hoping was solvable. It looks like questions about valgrind and Rust come up from time to time online in various places (including rust-lang.org) but nothing I've seen in them has helped me so far.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
Is there a method I could use to, say, instrument some of the widestring code to gauge when some of these leaked items are coming up? I have some leaks coming out of a clone() function and I want to break on it if it's got at least a certain number of characters. Whatever I do, the changes don't reflect in the build. I saw a suggestion that I adapted from online:
code:
cargo clean -p widestring
It looks like it does something to widestring when I build again, but I don't even get a basic hello print. The debugger is also pretty confused with what I'm doing.

I understand that this isn't the kosher way but it's not like I actually intend to make a permanent change to a dependency here or anything, so I figured there was some hack I could use.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I could never get valgrind to work but I think I got Heaptrack to work. It looks like I did actually fix a leak from it as something it showed went away after an alteration that I realized was necessary (not reclaiming a bunch of char*'s in vectors I created for a C call). However, there's still some real moonbeams flying out of this report. Take this:

code:
        let wchar_id = widestring::WideCString::from_str(unsafe_cstring
            .into_string()
            .unwrap())     <-- What I have created here apparently leaks
            .unwrap();
What's up with that?

It also looks like some vectors I'm making are dangling and causing leaks. Paraphrased code:
code:
        let (mut system_keys, mut system_values) = get_system_common();

        // Add more stuff to system_keys, system_values...

        let mut raw_keys: Vec<*const u32> = Vec::new();
        let mut raw_vals: Vec<*const u32> = Vec::new();

        for key in system_keys {
            raw_keys.push(key.into_raw())
        }

        for val in system_values {
            raw_vals.push(val.into_raw())
        }

It looks like when I iterate system_keys and values, I implicitly call into_iter() which moves ownership. If I switch to `for key in &system_keys`, my casting of key screws up:

code:
479 |             raw_keys.push(key.into_raw());
    |                           ^^^^^^^^^^^^^^ move occurs because `*key` has type `UCString<u32>`, which does not implement the `Copy` trait
What's going on there and how can I keep this stuff properly clean?

Edit: I'm also just generally surprised I'm leaking like this. Also, I should note later in the code, all those into_raw() calls do get reclaimed and dropped. I'm not leaking that stuff.

Rocko Bonaparte fucked around with this message at 08:01 on Jan 20, 2023

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
Ahhhhh you wrote back before I could qualify that. Those into_raw calls are getting properly reclaimed. I'm not leaking those.

(I was leaking those and already fixed it beforehand).

Adbot
ADBOT LOVES YOU

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
Overnight update after getting some sleep, I ended up just using as_ptr anyways. The fundamental problem with the casting was that into_raw() was giving me a mutable but I needed a constant reference for the C API signature, and I couldn't figure out how to do that.

I still don't really know why I'm leaking the way I am in all of these calls. I am just making a theory that I am loaning mutable stuff and since I'm not overtly reclaiming it, Rust is deciding not to drop it at the end of the function/scope. What I'm trying to do is add drops to stuff that is strangely leaking and seeing if the compiler writes me hate mail, fixing that, and then getting rid of the drop calls.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply