Live data from Hacker News

Cake – C23 and Beyond (2023)

thradams.com

31–40 of 128 posts

Re: Cake – C23 and Beyond (2023)

#31

Earlier quoted context omitted.

The real experience so far is the cake source itself.

Not sure I agree with that premise as the cake source would have been written in a way to be compatible with ownership annotations from the get go vs retrofitting an existing codebase. Help me understand how something like this composes: FILE* open_file(const char* p) { FILE* owner f = … return f; } Now open_file callers would need to know that ownership is being returned which means that local variables would need t…

Not sure if I understood. the usage of old and new (checked and unchecked) is a challenge.We may have the same headers used in both codes. The other challenging is that same source may compile in compiler with or without support.

Ownership Feature Strategy (Inspired by stdbool.h)

If the compiler supports ownership checks and qualifiers such as _Owner, _View, _Obj_view, etc., it must define __STDC_OWNERSHIP__.

However, even if the compiler implements ownership, it is not active by default. The objective is to have a smooth transition allowing some files without checks. For instance, a thirty part code inside your project.

For instance, when compiling this file, even if the compiler supports ownership we don't have errors or warnings because the checks are not enabled by default.

    #include 

    int main() {
      void \* p = malloc(1);
    }
A second define __OWNERSHIP_H__, is used to enable ownership. This define is set when we include at beginning.

    #include 
    #include 

    int main() {
      void \* p = malloc(1); //error: missing owner qualifier
    }
The other advantage of having a is because owner is a macro that can be defined as empty in case the compiler does not support ownership, allowing the same code to be compiled in compilers without ownership support.

Re: Cake – C23 and Beyond (2023)

#32

I might be missing something, but this seems to require ownership annotations on all functions, e.g. a compatible and correct prototype for `fclose` to correctly note that the owned `FILE *` is moved into the call. If that's correct, then this is somewhat practically limited: either pre-existing codebases will need to be retrofitted with an essentially bespoke set of macros, or the compiler will need to be "fail open…

currently cake uses existing msvc and gcc headers. These headers does not have any owner qualifiers.

The temporary solution, is the re-declare the malloc etc when compiling with cake and not complain withe the function signature difference only by owner qualifiers.

if this ownership were standard then gcc and mscv headers would have the qualifiers there enabled or not , but they would be there.

Re: Cake – C23 and Beyond (2023)

#33
post #27

C safety addons like this (there have been many) is that they don't prevent extracting raw pointers from controlled pointers. Optional memory safety isn't. > If this can be reasonably retrofitted to existing libraries and projects That's the problem. If you want to fool around in this space, consider revisiting C++ to Rust conversion. There's something called Corrode, which compiles C to a weird subset of Rust full o…

the cake implementation cannot be mapped to rust. I am not rust specialist but one concept for instance is that a owner pointer owns two resources at same time, the memory and object. In rust it is one concept.

Owner pointers take on the responsibility of owning the pointed object and its associated memory, treating them as distinct entities. A common practice is to implement a delete function to release both resources, as illustrated in Listing 7:

Listing 7 - Implementing the delete function

    #include 

    #include 


    struct X { 
      char *owner text; 
   };

    void x_delete(struct X *owner p) {
      if (p) {
        /*releasing the object*/ 
        free(p->text);
    
       /*releasing the memory*/ 
       free(p); 
     }
   }

   int main() {
      struct X \* owner pX = calloc( 1, sizeof \* pX);
      if (pX) {
       /*...*/;
       x_delete( pX); 
      }  
   }

Re: Cake – C23 and Beyond (2023)

#35

This is awesome. Could they reconcile this with [[gsl::Owner]] or gsl::owner somehow so we don't end up with multiple syntaxes in C++? https://reviews.llvm.org/D64448 https://github.com/microsoft/GSL/blob/main/docs/headers.md#g...

I think gsl::Owner is related with RAII.

The difference with cake ownership and RAII , is that with C++ RAII, the destructor is unconditionally called at end of scope. Then flow analysis is not required in RAII.

Cake requires flow analysis because "destructor" is not unconditionally called.

When the compiler can see that the owner is not owning a object (because the pointer is null for instance) then the "destructor" is not necessary.

To understand the difference.

With flow analysis (how it works today)

    int main() 
    {
      FILE *owner f = fopen("file.txt", "r"); 
      if (f)
        fclose(f);
    }

Without flow analysis (or with a very simple one, where the destroy must be the last statement)

    void fclose2(FILE * owner p) {
       if (p) fclose(p);
    }

    int main() 
    {
      FILE *owner f = fopen("file.txt", "r"); 
      if (f){
      }
      fclose2(f);
    }

Re: Cake – C23 and Beyond (2023)

#36

This is awesome. Could they reconcile this with [[gsl::Owner]] or gsl::owner somehow so we don't end up with multiple syntaxes in C++? https://reviews.llvm.org/D64448 https://github.com/microsoft/GSL/blob/main/docs/headers.md#g...

I think gsl::Owner is related with RAII. The difference with cake ownership and RAII , is that with C++ RAII, the destructor is unconditionally called at end of scope. Then flow analysis is not required in RAII. Cake requires flow analysis because "destructor" is not unconditionally called. When the compiler can see that the owner is not owning a object (because the pointer is null for instance) then the "destructor"…

the other difference in RAII destructor cannot be turned off. In cake the same object can be a "view"

    struct X x = {0};
    //...
    view struct X x2 = x;
    destroy(&x);
    //x2 does not need destructor

Re: Cake – C23 and Beyond (2023)

#37
post #27

C safety addons like this (there have been many) is that they don't prevent extracting raw pointers from controlled pointers. Optional memory safety isn't. > If this can be reasonably retrofitted to existing libraries and projects That's the problem. If you want to fool around in this space, consider revisiting C++ to Rust conversion. There's something called Corrode, which compiles C to a weird subset of Rust full o…

the cake implementation cannot be mapped to rust. I am not rust specialist but one concept for instance is that a owner pointer owns two resources at same time, the memory and object. In rust it is one concept. Owner pointers take on the responsibility of owning the pointed object and its associated memory, treating them as distinct entities. A common practice is to implement a delete function to release both resourc…

I don't see why that couldn't be represented like this in Rust:

    struct X {
        text: Option>,
    }
    fn main() {
        let pX = Box::new(X { text: None });
        // automatically dropped (freed) at end of scope
    }

Re: Cake – C23 and Beyond (2023)

#39
post #37

Earlier quoted context omitted.

the cake implementation cannot be mapped to rust. I am not rust specialist but one concept for instance is that a owner pointer owns two resources at same time, the memory and object. In rust it is one concept. Owner pointers take on the responsibility of owning the pointed object and its associated memory, treating them as distinct entities. A common practice is to implement a delete function to release both resourc…

I don't see why that couldn't be represented like this in Rust: struct X { text: Option >, } fn main() { let pX = Box::new(X { text: None }); // automatically dropped (freed) at end of scope }

In cake object and memory are two resources. We can for instance, delete the object and reuse the same memory.

For instance, this code is correct.

    #include  
    #include 

    struct X {
       char * owner text;
    };

    void x_delete(struct X * owner p)
    {
        if (p)
        {
           free(p->text);
           free(p);    
        }
    }

    int main() {   
       struct X * owner p = malloc(sizeof(struct X));
        
       p->text = malloc(10);

       free(p->text); //object text destroyed

       struct X x2 = {0};

       *p = x2; //x2 MOVED TO *p

       x_delete(p);   

       //no need to destroy x2
    }

Re: Cake – C23 and Beyond (2023)

#40

This is overly complicated, there is no need to bring Rust semantics to C to ensure memory safety. A good mempool implementation is all you need (i.e keeps track of every request, and zeros out the memory on release)

Compiler optimizations and other forms of UB like integer overflow would like a word with you. If it were that simple, someone would have had success at scale by now https://alexgaynor.net/2020/may/27/science-on-memory-unsafet....
Post reply on HN