From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-0.8 required=5.0 tests=DKIM_ADSP_CUSTOM_MED, DKIM_INVALID,DKIM_SIGNED,FREEMAIL_FROM,MAILING_LIST_MULTI autolearn=ham autolearn_force=no version=3.4.4 Received: (qmail 9953 invoked from network); 31 Jan 2023 12:28:59 -0000 Received: from minnie.tuhs.org (50.116.15.146) by inbox.vuxu.org with ESMTPUTF8; 31 Jan 2023 12:28:59 -0000 Received: from minnie.tuhs.org (localhost [IPv6:::1]) by minnie.tuhs.org (Postfix) with ESMTP id 56CAD425CF; Tue, 31 Jan 2023 22:28:35 +1000 (AEST) Received: from mail-lj1-f171.google.com (mail-lj1-f171.google.com [209.85.208.171]) by minnie.tuhs.org (Postfix) with ESMTPS id D19EB425CE for ; Tue, 31 Jan 2023 22:28:29 +1000 (AEST) Received: by mail-lj1-f171.google.com with SMTP id u27so9186352ljo.12 for ; Tue, 31 Jan 2023 04:28:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=Mx41Y/oXDwd9kxWrUfulpptiX0OW0/sXPusruOxnSlU=; b=CmSdRYowoGmZzjWsUbhROdoYCUE/lJKg1nGa1wrcDt9RuIlwrNUa4a+MgHpBN6ljQB weaNv+ogB0MnRIz7QmS9uNtwZJtUUYSmpMFm22bdpL4tJ4OP2+ATZdQ2mAb5lq4f+T3R BKwOdXDwef2Zl7glWO1u/HH8hoG1GiAgxmmnatCQBkrgsw2fKbXHW50Z5aOr8nqyalUL G3aELiPcp3YMy6f8IyryvCWOd8pFcier/dAU/Sd1ffyhvoHC23xZt+7f3gH88cl8PCp4 DGUkENtkg9NUHO4qzYNFbRyywjIbqV2ySvry+/qovB1UYYHIYkhoj2ZPGtcRP9gZK78g XXPg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=Mx41Y/oXDwd9kxWrUfulpptiX0OW0/sXPusruOxnSlU=; b=y4Kk7GbJCRt77vZJr95C6EU3Lz0JsaVuJaHD8UNDUYVBiy6XhNn8xUx/c9DdcuyKgY PzGIMEUbWR4+goXuYuF11N0cQ3GlW+/4Ij/jGK3FkrA29hsWk+4TFaMdQO2VO3iPd6QL m5PFRoNmYavXhHTCMdetzO6cKfcR5a+7HrXVs5ppvNy8DFgiPIXgOjkqa+LSLX4BpYWE wvyuwyynvf5iCfJyt2cQVKM+85co9uzMeQrZuk3WEGZv15s57ZIs8HaIjBTWfiyPTfCC AZKqr5k5eeJCMw2i+t0llTjm3gO+RjWlWCSifeqtva7Zme2zV1Do44RuSIvdaejU+AG4 kR/Q== X-Gm-Message-State: AO0yUKUkSmQ2x6zNF4hFjorsvjBa8V2NjqNf75NXkrlNN9jR46aMOZZ3 A5DAyY1NPXyzs1LXARCkCbQsA3UrZJdsCduXXpLYeBR9 X-Google-Smtp-Source: AK7set/rXKTmYb4Oq05+hbWPaxod78FSoYnhr/75Lyr0efmbat6SaFBEajbD9KIWG5vWDEt2i/q4WsM5wBpn/1qJSO4= X-Received: by 2002:a2e:3c1a:0:b0:28f:23ce:1a20 with SMTP id j26-20020a2e3c1a000000b0028f23ce1a20mr2433862lja.156.1675168047864; Tue, 31 Jan 2023 04:27:27 -0800 (PST) MIME-Version: 1.0 References: In-Reply-To: From: Dan Cross Date: Tue, 31 Jan 2023 07:26:51 -0500 Message-ID: To: ron minnich Content-Type: text/plain; charset="UTF-8" Message-ID-Hash: BWL4NP6BMNFQ3G23IVHM4PGF7FRIJ7IV X-Message-ID-Hash: BWL4NP6BMNFQ3G23IVHM4PGF7FRIJ7IV X-MailFrom: crossd@gmail.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-tuhs.tuhs.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Alejandro Colomar , segaloco , TUHS X-Mailman-Version: 3.3.6b1 Precedence: list Subject: [TUHS] Re: yet another C discussion (YACD) and: Rust is not C++ List-Id: The Unix Heritage Society mailing list Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: On Mon, Jan 30, 2023 at 10:59 PM ron minnich wrote: > That example was a simplified bit of code from a widely used code base. All I need to do is change the function g go a pointer to function, or have it be provided by a .so, and all bets are off. > > In any event, the important thing here is not that y should be initialized, or should not; it's that it is not possible to get a consistent answer on the question, from people who have been writing in C for decades. Indeed, I was agreeing with you, Ron. :-) - Dan C. > On Mon, Jan 30, 2023 at 6:56 PM Dan Cross wrote: >> >> On Mon, Jan 30, 2023 at 8:49 PM Alejandro Colomar >> wrote: >> > Hello Ron, >> > >> > On 1/30/23 20:35, ron minnich wrote: >> > > I don't know how many ways there are to say this, but Rust and C/C++ are >> > > fundamentally different at the lowest level. >> > > >> > > If you are just looking at Rust syntax in a superficial way, you might be >> > > excused for thinking it's "C with features / C++ with differences." >> > > >> > > But that's not how it is. It's like saying C is "just like assembly" because >> > > labels have a ':' in them; or that Unix is "just like RSX" because they have >> > > vaguely similar commands. >> > > >> > > Here's a real question that came up where I work: should the code shown below be >> > > accepted (this is abstracted from a real example that is in use ... everywhere)? >> > > We had one code analyzer that said, emphatically, NO; one person said YES, >> > > another MAYBE. One piece of code, 3 answers :-) >> > > >> > > char f() { >> > > char *y; >> > > g(&y); >> > > return *y; >> > > } >> > > >> > > >> > > A specific question: should y be initialized to NULL? >> > >> > No. At least not if you don't want to use the value NULL in your program. >> > Using NULL as something to avoid Undefined Behavior is wrong, and it will >> > contribute to hide programmer errors. >> >> Sorry, I think this misses the point: how do you meaningfully tell >> that `g` did something to `y` so that it's safe to indirect in the >> `return`? >> >> On the other hand, one could write, >> >> char f() { >> char *y = NULL; >> g(&y); >> if (y == NULL) >> panic("g failed"); >> return *y; >> } >> >> C, of course, can't tell in the original. And while you can now tell >> that `g` did _something_ to `y`, you still really don't know that `y` >> points to something valid. >> >> > These days, compilers and static analyzers are smart enough to detect >> > uninitialized variables, even across Translation Units, and throw an error, >> > letting the programmer fix such bugs, when they occur. >> >> In many cases, yes, but not in all. That would be equivalent to >> solving the halting problem. >> >> > The practice of initializing always to NULL and 0 provides no value, and >> > silences all of those warnings, thus creating silent bugs, that will bite some >> > cold winter night. >> > >> > I know some static analyzers (e.g., clang-tidy(1)) do warn when you don't >> > initialize variables and especially pointers (well, you need to enable the >> > warning that does that, but it can warn). That warning is there due to some >> > coding style or certifications that require it. I recommend disabling those >> > bogus warnings, and forgetting about the bogus coding style or certification >> > that requires you to write bogus code. >> >> Oh my. >> >> > > The case to set y to NULL: otherwise it has an unknown value and it's unsafe. >> > >> > Is an undefined value less safe than an unexpected one? I don't think so. At >> > least compilers can detect the former, but not the latter. >> > >> > > The case against setting y to NULL: it is pointless, as it slows the code down >> > > slightly and g is going to change it anyway. >> > >> > Performance is a very minor thing. But it's a nice side-effect that doing the >> > right thing has performance advantages. Readability is a good reason (and in >> > fact, the compiler suffers that readability too, which is the cause of the >> > silencing of the wanted warnings. >> > >> > > The case maybe: Why do you trust g() to always set it? Why don't you trust g()? >> > > convince me. >> > >> > Well, it depends on the contract of g(). If the contract is that it may not >> > initialize the variable, then sure, initialize it yourself, or even better, >> > check for g()'s errors, and react when it fails and doesn't initialize it. >> > >> > If the contract is that it should always initialize it, then trust it blindly. >> > The compiler will tell you when it doesn't happen (that is, when g() has a bug). >> >> The number of situations where the compiler can't tell whether `g` has >> a bug is unbounded. >> >> > > You can't write this in Rust with this ambiguity. It won't compile. In fact, & >> > > doesn't mean in Rust what it does in C. >> > >> > I don't know Rust. Does it force NULL initialization? If so, I guess it's a >> > bad design choice. Unless Rust is so different that it can detect such >> > programmer errors even having defined default initialization, but I can't >> > imagine how that is. >> >> Rust enforces that all variables must be initialized prior to use. >> Whether they're initialized with a zero value or something else is up >> to the programmer; but not initializing is a compile-time error. >> >> For example: >> >> | fn main() { >> | let x; >> | if thing_is_true() { >> | x = 5; >> | } else { >> | x = 3; >> | } >> | println!("x={x}"); >> | } >> >> In fact, this is good; this allows us to employ a technique called, >> "Type-Driven Development", whereby we can create some type that >> encodes an invariant about the object. An object of that type is >> written in such a way that once it has been initialized, the mere >> existence of the object is sufficient to prove that the invariant >> holds, and need not be retested whenever the object is used. For >> example: >> >> | #[repr(transparent)] >> | struct PageFrameAddr(u64); >> | impl PageFrameAddr { >> | fn new_round_down(addr: u64) -> PageFrameAddr { >> | PageFrameAddr(addr & !0xFFF) >> | } >> | } >> >> Here, "PageFrameAddr" contains a 4KiB-aligned page address. Since the >> only way to create one of these is by the, `new_round_down` associated >> method that masks off the low bits, we can be sure that if we get one >> of these, the contained address is properly aligned. In C, we'd >> pretty much have to test at the site of use. >> >> This is an extremely powerful technique; cf Alexis King's blog post, >> "Parse Don't Validate" >> (https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/) >> and Cliff Biffle's talk on the Hubris embedded RTOS >> (https://talks.osfc.io/osfc2021/talk/JTWYEH/). >> >> > > Sorry to be such a pedant, but I was concerned that we not fall into the "Rust >> > > is C++ all over again" trap. >> > > >> > > As for replacing C, the velocity of Rust is just astonishing. I think folks have >> > > been waiting for something to replace C for a long time, and Rust, with all its >> > > headaches and issues, is likely to be that thing. >> > >> > Modern C is receiving a lot of improvements from C++ and other languages. It's >> > getting really good in fixing the small issues it had in the past (and GNU C >> > provides even more good things). GNU C2x is quite safe and readable, compared >> > to say ISO C99 versions. >> >> C23 looks like it will be a better language that C11, but I don't know >> that even JeanHeyd would suggest it's "quite safe". :-/ >> >> - Dan C. >> >> >> > I don't think C will ever be replaced. And I hope it doesn't. >> > >> > Possibly, something like with Plan9 and Unix/Linux will happen. The good things >> > from other languages will come back in one form or another to C. The >> > not-so-good ones will be discarded. >> > >> > > >> > > Personally, I still prefer Go, but I can also see which way the wind is blowing, >> > > especially when I see Rust use exploding in firmware and user mode, and now even >> > > in the Linux kernel. >> > >> > Cheers, >> > >> > Alex