Skip to content

CString does not preserve capacity #74794

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
kotauskas opened this issue Jul 26, 2020 · 1 comment
Open

CString does not preserve capacity #74794

kotauskas opened this issue Jul 26, 2020 · 1 comment
Labels
C-bug Category: This is a bug. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@kotauskas
Copy link

Simplest repro:

use std::ffi::CString;
let vec = Vec::with_capacity(87);
let cstring = CString::new(vec);
let vec = cstring.into_bytes();
assert_eq!(vec.capacity(), 87);

I expected CString to behave like String, preserving capacity from the Vec it was created. Instead, the CString implementation shrinks-to-fit and stores a boxed slice, which is then converted back into Vec in into_bytes/into_bytes_with_nul, giving back as much capacity as there were elements, i.e. 1 which is the nul terminator.

I vaguely understand the reasoning for this — when &CStr becomes a narrow pointer, Box<CStr> would be a narrow pointer too, meaning that CString also will; in such a case, if CString was a Vec instead, it would be three pointers in size (pointer, size, capacity). This means, however, that there's no reason to use CString instead of Box<CStr>, making it essentially useless.

In other words, the only reason for String/OsString/CString to exist in parallel with Box<str>/Box<OsStr>/Box<CStr> is to provide the same safety guarantees for the contents while also providing Vec-like functionality (growing/shrinking and spare capacity). In reality, CString does not provide those at all, much like OsString (though it'd be considerably more complex to implement push/pop for OsString on Windows even if it's a Vec, since that'd mean that encoding and decoding the underlying WTF-8 would be required).

As an initial effort, OsString and CString can be transformed into Vecs transparently to their public APIs. Then, the Vec API can be integrated via the usual RFC process.

Meta

rustc --version --verbose:

rustc 1.46.0-nightly (3503f565e 2020-07-02)
binary: rustc
commit-hash: 3503f565e1fb7296983757d2716346f48a4a262b
commit-date: 2020-07-02
host: x86_64-unknown-linux-gnu
release: 1.46.0-nightly
LLVM version: 10.0
@kotauskas kotauskas added the C-bug Category: This is a bug. label Jul 26, 2020
@Mark-Simulacrum Mark-Simulacrum added C-feature-request Category: A feature request, i.e: not implemented / a PR. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. and removed C-bug Category: This is a bug. labels Jul 26, 2020
@retep998
Copy link
Member

I don't know why OsString is being dragged into this. At least on Windows OsString is a wrapper around Vec<u8>, and OsString has APIs to work with its capacity. That said it would be great to have more methods on OsString to manipulate it directly.

@kotauskas kotauskas changed the title CString and OsString do not preserve capacity CString does not preserve capacity Jul 27, 2020
@Dylan-DPC Dylan-DPC added C-bug Category: This is a bug. and removed C-feature-request Category: A feature request, i.e: not implemented / a PR. labels Jan 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants