Re: [EE] Ideas about improving safety in C language
smplx <[email protected]>
| Newsgroups | gmane.comp.hardware.microcontrollers.pic |
|---|---|
| Message-ID | <[email protected]> |
Hi Isaac,
Very good. I look forward to reading the source code when time permits.
One thought, you might consider adding a field in the string descriptor
that is initialised to the address of the descriptor. That way if the
descriptor is copied then the underlying library can detect it. You could
use this info when changing the pointer to the payload (e.g. realloc) to
trap the error.
A possible accidental copy would occure if the string is passed by value
instead of reference.
Friendly Regards
Sergio Masci
On Wed, 23 Apr 2025, Isaac Marino Bavaresco wrote:
> Hi Sergio,
>
> Sorry for the late reply. I was busy but wanted to comment on your
> message, so I saved it for later.
>
>
> Em 18/04/2025 20:39, smplx escreveu:
>>
>>
>> On Fri, 18 Apr 2025, Isaac Marino Bavaresco wrote:
>>
>>> Hi Sergio,
>>>
>>>
>>> The problem you mention in (2) is not related to strings or any other
>>> data structure in particular, but to threads themselves. And for
>>> that, there are measures to solve or mitigate them. In short, if data
>>> is being corrupted by another thread, then the programmer messed up
>>> by not using a mutex or other mechanism.
>>
>> Hi Isaac,
>>
>> No you've missunderstood.
>>
>> Any function can be considered a form of thread but every thread
>> cannot be considered a function. By considering functions as threads I
>> am reducing the amount of work necessary to discuss the problem. When
>> function FOO invokes function BAR, function BAR can be described as a
>> thread that is launched by function FOO. FOO prepares the context
>> within which BAR executes and then launches it. Often BAR will run to
>> completion before FOO resumes,
>
>
> In this case, we have the normal function call. When BAR returns and FOO
> resumes, any changes made by BAR to the variables will be visible to
> FOO, so no problem here.
>
>
> If FOO takes a mutex before calling BAR, and then BAR tries to take the
> mutex too, it will get the mutex, because from the system's perspective
> it is just the same thread taking the mutex recursively. The system will
> just increase the mutex's count and let BAR run. When BAR releases the
> mutex, the mutex's count will be decreased and when FOO releases the
> mutex the count will reach zero and the mutex will be really free.
>
>
>> sometimes BAR will continue asynchronously and run concurrently with FOO.
>
>
> Here we have the "traditional" meaning of threads.
>
>
>> If FOO invokes a mutex on a string that BAR needs to modify then a
>> deadlock will most likely occure.
>
>
> It depends. If FOO takes the mutex before spawning BAR, then BAR tries
> to take the mutex and at the same time FOO is waiting for BAR to run to
> completion, then of course a deadlock will occur.
>
> In this case, perhaps it is not an application that requires threads, it
> most likely would be better done with just a function call as FOO will
> wait for BAR's completion anyway.
>
> In a different scenario, if FOO takes the mutex then spawns BAR, FOO
> will be able to finish its business with the string (or any other data)
> and release the mutex, then BAR will be able to do its part of the job
> with the string. No deadlock.
>
>
>>
>> Consider:
>>
>> BAR(char *str, int pos, char *stuff)
>> {
>> int len1, len2, j;
>>
>> len1 = strlen(str);
>>
>> len2 = strlen(stuff);
>>
>> str = realloc(str, len1 + len2 + 1 - 1);
>>
>> // make space at pos
>> for (j=len1+len2; j>pos+len2; j--)
>> {
>> str[j] = str[j-1];
>> }
>>
>> // insert 'stuff' at pos
>> for (j=0; stuff[j]!='\0'; j++)
>> {
>> str[pos+j] = stuff[j];
>> }
>> }
>>
>>
>> FOO(char *str, char *stuff)
>> {
>> int j;
>>
>> for (j=0; str[j]!='\0'; j++)
>> {
>> if (str[j] == '@')
>> {
>> BAR(str, j, stuff);
>>
>> // at this point str might have been moved
>> // but the pointer str will not have been
>> // updated
>> }
>> }
>> }
>>
>
>> For the above 'str' to be safe, there needs to be a string structure
>> (descriptor) that is independent of the string "payload"
>
>
> Well, that was my suggestion from the beginning...
>
> Check my code on GitHub.
>
>
>> such that the payload can be moved about in memory while the
>> descriptor does not move and the individual characters within the
>> string are always accessed using the desciptor (lingering pointers to
>> char are prohibited). This would require the compiler to understand
>> when a pointer to char is actually a pointer to a char within a string.
>>
>> I have actually done some work on this in XCSB v3 but ill health has
>> made this a sporadic project.
>>
>>>
>>> The problems I was referring to are the ones you mention in (1), that
>>> is, problems pertaining to string manipulation specifically. Standard
>>> C library functions are unsafe (they do not check maximum length of
>>> the destination string, for instance). It is possible to implement
>>> better functions that take the size of the destination string as an
>>> argument (they do exist, see 'strlcat', for instance), but the
>>> programmer can always pass a wrong size by mistake.
>>>
>>> What I'm suggesting is a completely new data type, that besides the
>>> characters themselves it stores information about maximum length,
>>> current used length, etc. and that is manipulated in the same way it
>>> is done for the present standard strings.
>>
>> I would strongly recommend that you break the string into 2 parts, the
>> string descriptor and the string payload. That way you can keep the
>> descriptor in a constant location while the payload hops around.
>
>
> My first implementation creates strings in only one chunk, so they
> cannot grow beyond the maximum size they were specified upon creation.
> I'm thinking about the better way to implement a new version that can
> grow (or shrink) dynamically. I'm trying to create an implementation
> able to deal with both types, with the programmer choosing which type he
> wants to use each time.
>
>
>>
>>
>> In C++ you could actually operload the "[]" operator but good luck
>> getting programmers to NOT short circuit this with "char *ptr".
>
>
> I'm more interested in a C implementation, that is what I need for
> embedded systems. A C++ implementation seems less necessary, because, as
> somebody already mentioned, it already has std::string.
>
> Unfortunately C doesn't have function overloading. I think that some of
> C++'s features could be ported back to C, such as passing arguments by
> reference and templates, but function overloading seems too much.
>
>
>>
>>>
>>> Of course it is not possible to have a 100% transparent and seamless
>>> implementation without the compiler's awareness (that is, implement
>>> the new strings in the language standard), but a fairly good solution
>>> could be created by just creating a new library.
>>
>> I wish you good luck
>
>
> A man can dream...
>
>
> Cheers,
>
> Isaac
>
>
>>
>> Friendly Regards
>> Sergio Masci
>
> --
> O software antivírus Avast realizou uma checagem de vírus neste e-mail.
> www.avast.com
> --
> http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive
> View/change your membership options at
> https://mailman.mit.edu/mailman/listinfo/piclist
>
--
http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive
View/change your membership options at
https://mailman.mit.edu/mailman/listinfo/piclist