Jump to content
Die Holländer

Delphi and "Use only memory safe languages"

Recommended Posts

I wish they added interfaces to existing RTL classes, this would be nice backwards compatible way to improve memory management.

Share this post


Link to post
6 minutes ago, EugeneK said:

I wish they added interfaces to existing RTL classes, this would be nice backwards compatible way to improve memory management.

How would that be backward compatible? Classes that use reference counting have completely different memory management and require slightly different handling than ones that are not reference counted. Every line of code that would use such changed classes would have to be inspected and changed.

 

This would be like having ARC compiler all over again, only without half of required changes being automatically implemented in the compiler. You cannot force ARC on existing code that is not written with ARC in mind. That does not work. It may work in some simple scenarios, but then when you get to slightly more complex code is all falls apart.

Share this post


Link to post
16 minutes ago, Dalija Prasnikar said:

How would that be backward compatible? Classes that use reference counting have completely different memory management and require slightly different handling than ones that are not reference counted. Every line of code that would use such changed classes would have to be inspected and changed.

 

This would be like having ARC compiler all over again, only without half of required changes being automatically implemented in the compiler. You cannot force ARC on existing code that is not written with ARC in mind. That does not work. It may work in some simple scenarios, but then when you get to slightly more complex code is all falls apart.

I was thinking something like TXmlDocument/IXmlDocument, if you use TXmlDocument you continue using regular Create/Free or component ownership and if you use IXmlDocument it is reference counted.

Share this post


Link to post
Posted (edited)
1 hour ago, JonRobertson said:

The memory manager would have to "know" when the memory was no longer needed, otherwise it would release allocated memory too soon.

This would be called Tracing garbage collection.

 

But as Dalija already explained the crux is not which way of automatic memory reclamation is being used but the fact that it would be a mix of different ones that don't play together nicely.

Edited by Stefan Glienke
  • Like 1

Share this post


Link to post
11 hours ago, EugeneK said:

I was thinking something like TXmlDocument/IXmlDocument, if you use TXmlDocument you continue using regular Create/Free or component ownership and if you use IXmlDocument it is reference counted.

First, that is not proper description how TXmlDocument memory management works - I understand it is possible that you just wanted to convey what you meant by adding interfaces to RTL classes (and that served the purpose), but I need to add precise explanation of how it works because that class is one of the most incorrectly used ones when it comes to memory management.

 

The deciding factor in how the TXmlDocument memory is managed is not in how it is stored (reference type, although it does have a play in how the code will behave), but whether you have constructed the instance with nil owner or not. This will set FOwnerIsComponent field and depending on that field the instance will be automatically managed with reference counting or not. If the owner is nil, you must store created instance in interface reference and if the owner is not nil, then you may store it in either interface reference or object reference, but the memory will not be managed by interface reference if you do that and you must make sure that interface reference does not outlive owner.

 

Following console application demonstrates this. XmlDocInterafce and XmlDocComponent show correct usage, the other two are incorrect ones that can cause trouble depending on the code (you can get lucky and avoid issues, but that does not mean that such usage is correct and will not blow when you least expect it)

 

program XMLDocMM;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  System.Classes,
  Winapi.ActiveX,
  Xml.Win.msxmldom,
  Xml.XMLDoc,
  Xml.XMLIntf;

var
  Owner: TComponent;

procedure UseDoc(Doc: IXMLDocument);
begin
  Doc.LoadFromXML('<abc>aaa</abc>');
end;

procedure XmlDocInterface;
var
  x: IXMLDocument;
begin
  x := TXMLDocument.Create(nil);
  UseDoc(x);
  Writeln(x.IsEmptyDoc);
end;

procedure XmlDocInterfaceLeak1;
var
  // this will create leak as reference counting is not properly triggered
  x: TXMLDocument;
begin
  x := TXMLDocument.Create(nil);
  x.LoadFromXML('<abc>aaa</abc>');
  Writeln(x.IsEmptyDoc);
end;

procedure XmlDocInterfaceLeak2;
var
  x: IXMLDocument;
begin
  x := TXMLDocument.Create(Owner);
  UseDoc(x);
  Writeln(x.IsEmptyDoc);
  // this will create memory leak as memory is not managed by interface reference, but owner
  Owner.RemoveComponent(TComponent(x));
end;

procedure XmlDocComponent;
var
  x: TXMLDocument;
begin
  x := TXMLDocument.Create(Owner);
  try
    UseDoc(x);
    Writeln(x.IsEmptyDoc);
  finally
    x.Free;
  end;
end;

procedure XmlDocComponentSelfDestruct;
var
  x: TXMLDocument;
begin
  x := TXMLDocument.Create(nil);
  try
    UseDoc(x);
    // x will be destroyed here
    Writeln(x.IsEmptyDoc); // accessing destroyed instance
  finally
    // Invalid Pointer Operation
    x.Free;
  end;
end;

begin
  ReportMemoryLeaksOnShutdown := True;
  CoInitialize(nil);
  try
    Owner := TComponent.Create(nil);
    try
      XmlDocInterface;
      XmlDocInterfaceLeak1;
      XmlDocInterfaceLeak2;
      XmlDocComponent;
      XmlDocComponentSelfDestruct;
    finally
      Owner.Free;
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  CoUninitialize;
end.

 

So if you want to add interfaces to some RTL class and change its memory management behavior, you cannot do that just by adding interface to its declaration and required reference counting methods and let the reference type decide the memory management. I mean in simple scenario you could, but such code would be very fragile. Following code works correctly when it comes to memory management, but if the reference counting is in any way triggered by second example (Test2) it would auto destroy the object instance.

 

procedure Test1;
var
  i: IInterface;
begin
  i := TInterfacedObject.Create;
end;

procedure Test2;
var
  o: TInterfacedObject;
begin
  o := TInterfacedObject.Create;
  o.Free;
end;

 

So, if you want to have such class that can have its memory managed in dual way, you need to handle that through some additional parameter during instance construction (or through some special value of existing parameter, like it was done with TXmlDocument) that would prevent accidental reference counting from destroying the object prematurely. And then you would also have to pay attention on how you store such instance and that reference type matches passed parameter and associated memory management.

 

On top of that, you would need to declare interface for the instance public API because otherwise you would not be able to use any of the object's intended functionality. With TXmlDocument the whole functionality is already interface based, so exposing that through outer wrapper is trivial.

 

In real life scenarios, if you need to automatically manage some object instance, there are better ways to do that (through some kind of smart pointer implementations or similar) than by forcing interfaces on those base classes. I had such base class in my library as part of some base class hierarchy but I don't use that ability except in few rare cases. I though I would use it more, but adding it on such low level was a mistake as I almost never used it across span of 20 years I had it. Classes that had interfaces defined I used through interface references anyway, there was never a need to switch to manual memory management for those, and occasional usage of automatic memory management for other classes that didn't have declared interfaces was not enough to justify the implementation in the base class. Main reason was that using such class with dual memory management without having its specific interface was more complicated than using smart pointers or just writing few extra lines of code and doing it manually.

 

I am not saying that sometimes such dual memory management is not useful, but that such instances are rare and adding such thing on majority of RTL classes would be waste of time and effort.

 

Share this post


Link to post
21 hours ago, JonRobertson said:

"Promoting tools to help in this area" sounds good. But "Sounds good" is marketing rubbish.

Exactly, that's why I laughed about that whole discussion, because the core question is pretty clear.
Maybe I should add an <irony> tag, to make that more clear to everybody.

The core question: Delphi is NOT memory-safe ... period.

 

If some institutions think otherwise, and Embarcadero likes to use that statement for marketing purposes, ... so what?!

 

Do you expect Embarcadero shall deny and contradict such an official statement from the government?

Probably not, I wouldn't do either.

 

Let's embrace these statements and use them as marketing for Delphi too. :classic_cheerleader:

Every help from inside and outside is welcome, IMHO.

 

 

  • Like 2

Share this post


Link to post
16 hours ago, Stefan Glienke said:

This would be called Tracing garbage collection

Although I've been programming for 42 years, I know so little compared to how much there is to know. So thanks for the link.

 

My preference is to handle/control the lifetime of memory allocations based on the purpose and usage, rather than leaving it to algorithms that attempt to figure that out.

 

The code below is a hand-slap, don't ever do that. It was also the first thought I had to show that the memory manager does not "know" anything, unless it is told.  Algorithms may be written to read my mind. But I digress...

function BadAlloc(Size: NativeInt): String;
begin
  var pStr: PChar;
  GetMem(pStr, Size);
  StrPCopy(pStr, 'bad code');
  Result := IntToStr(Integer(pStr));
end;

procedure BusyProc;
begin
  var myBad := BadAlloc(20);
  // lots of other busy code...
  ShowMessage(PChar(StrToInt(myBad)));
end;

My expectation is that tracing garbage collection could release the 20 byte block immediately after BadAlloc returns, or any other time before the ShowMessage is executed.

Share this post


Link to post
On 3/8/2024 at 1:28 AM, David Schwartz said:

TL;DR -- Pointer aliases are inconsequential. Pointer math is extremely hazardous.

Nevertheless, all of the non-trivial projects I work on make use of pointer math too. What you say about pointer math, speed, and what companies want, may be true in many cases, but extrapolating from that to your original claim about pointers (math or aliases, regardless) is quite a leap. They have not "pretty much disappeared from use." One example that comes to mind is a custom 8-bit bitmap backing we developed that would be excruciatingly slow were it not for basic, simple, tried-and-true pointer arithmetic.

 

The reality is also that even libraries that don't offer access to these programming methods still make use of them internally. Somewhere, someone is doing the pointer math.

Share this post


Link to post
On 3/11/2024 at 5:42 AM, David Heffernan said:

This is so stupid. Delphi and C++ are exactly the same in this regard.

The convergence of documents written by government bureaucrats and corporate marketers would produce nothing other than stupid.

Share this post


Link to post
2 hours ago, Rollo62 said:

The core question: Delphi is NOT memory-safe ... period.

About this !

 

I am sorry but will try again with different method to explain why few users here is missing the right angel to look at this.

 

So:

1) The memory safety in all these articles and publication are not about what you think is, though few of them miss name the problem or miss use the term in wrong places, this is the problem when there is no clear definition.

 

2) The most memory safe language is JavaScript, I honestly believe that, as stupid as it sound, BUT you must understand what are we describing here, see, it is near impossible to write JS code and take over a PC, can you ? and the question is not that, to be exact can you escalate memory failure within JS code to execute out of bound code aka hijack the execution ? NOPE, you can't !

JS is almost always runs in a special VM with interpreter, so you need to escalate a memory violation to escape that VM which in %99 run inside isolated process of browser then hijack the execution there, then escape the host browser process itself, then trigger malicious execution in the host that runs the browser, .... JS is memory safe for this subject, which is escalating memory triggered violation by malicious data (again data) to execute managed or unmanaged code (malicious or whatsoever aka DDoS) 

 

3) I am mathematician by education, and i tend to an abstract(s) everywhere, this helps me, so lets look at this but from different perspective, one said he can compare potatoes and grapes, may be farmers and cooks will lose their shit, while i am fine with it, it is his build, abstract, math realm ... call it what ever you want, and let him call it as he wish, he managed to compare potatoes and grapes, and without understanding this scale we can't argue with rightness not we can call it fallacy, he might be comparing the percent of water or Zinc ... in both, or something not very usual like the shade of color in comparison HTML color names then sorts these names then put the grape or the potato in a scale of it, 

You know what we don't care about this abstract we care about different thing, there is a scale so we can use it, When all these companies shouting about memory safety, well they have the best developer and programmers in the world, i mean literally the best end there, and their code with be reviewed many times, and these companies like Apple, Google, Microsoft, Oracle, IBM ...they don't cheap out on bugs and security, i am sure they tried everything they could, and now they are throwing the towel, no matter how good and experienced their developers, they again and again do the same mistakes and same wrong doing, causing security bug and CVE, these cost money and reputation, remember these CVE are fixed and patched by the same experienced top shelf programmers, yet again they doomed to repeat the same.

This also goes for open source software like Linux and Mozilla, literally the memory safety induced breach is there and no one can see it, and nor AI.

 

Anyway, they are throwing the towel now and switch to prevent the developer from doing smart stuff, and limit their lanes, Rust is very strict and fit those needs, and that why all of these as C++ is way too much powerful and the developers tend grab it and start swing, the approach of investing in the developers them self, looks like failed or didn't yield the required result, so switching to different approach like changing the tooling.

 

Again memory safety is not from powerful language as powerfulness is irrelevant here, but from consequences of using that language to handle data in the memory.

 

4) They all managed to have a scale to compare Rust and C/C++ in memory safety (again within the context explained above), then we can use the same scale for Delphi.

5) C++ is way more powerful than Rust, and there is nothing can't be done with C++ that Rust has, yet we are talking about different problem the ignoring the human factor, the one that made all these companies give up on their developers, and all these 3 letters agencies recommend, they all saw stuff and shit.

 

back to this

2 hours ago, Rollo62 said:

The core question: Delphi is NOT memory-safe ... period.

It is not !, but wait what are we talking about ? is memory-safe in your phrase is the same as my above or in the articles ? the same perspective ? 

 

It is not !, yet it is safer than C++, just because we are limited with stack usage, and our variables allocated before hand.

 

 

Share this post


Link to post
55 minutes ago, Kas Ob. said:

yet it is safer than C++

It's not safer than C++, it's exactly the same as C++

  • Like 1

Share this post


Link to post
2 minutes ago, David Heffernan said:

It's not safer than C++, it's exactly the same as C++

If C++ compiler allocated all vars upfront and didn't use PUSH/POP inside any scope of code then they will be closer.

  • Like 1

Share this post


Link to post
5 hours ago, Dalija Prasnikar said:

So if you want to add interfaces to some RTL class and change its memory management behavior, you cannot do that just by adding interface to its declaration and required reference counting methods and let the reference type decide the memory management. I mean in simple scenario you could, but such code would be very fragile. Following code works correctly when it comes to memory management, but if the reference counting is in any way triggered by second example (Test2) it would auto destroy the object instance.

 

Of course you don't just add interface to declaration, some work is needed but all your description does not say that it can't be implemented in backwards compatible way. And doing it class by class is much easier than adding ARC to whole compiler.

 

Quote

 

So, if you want to have such class that can have its memory managed in dual way, you need to handle that through some additional parameter during instance construction (or through some special value of existing parameter, like it was done with TXmlDocument) that would prevent accidental reference counting from destroying the object prematurely. And then you would also have to pay attention on how you store such instance and that reference type matches passed parameter and associated memory management.

 

All classes that take TComponent owner already need to be manually freed when passed nil as a parameter. There could be bugs because of double free/memory leak because of this too.

 

Quote

 

On top of that, you would need to declare interface for the instance public API because otherwise you would not be able to use any of the object's intended functionality. With TXmlDocument the whole functionality is already interface based, so exposing that through outer wrapper is trivial.

 

Exactly! That's the whole point, it also has other advantages, like ability to provide different implementation for classes.

And TComponent seems to already implement interface reference counting, so maybe all that is needed to add interface implementing public methods.

Quote

 

In real life scenarios, if you need to automatically manage some object instance, there are better ways to do that (through some kind of smart pointer implementations or similar) than by forcing interfaces on those base classes.

 

You never really need automatically manage memory, you can always free it manually it just a big source of bugs. I think goal of compiler developers should be to give people options to avoid them and write simpler code. Just now I found 10 year old bug where TStrings object was assigned to already created object causing memory leak, this kind of bug is almost impossible to find and it would not be a problem if it was IStrings instead.

For smart pointers I don't really see a way to use them as elegantly as interfaces, at least with current Delphi language.

 

Quote

 

I am not saying that sometimes such dual memory management is not useful, but that such instances are rare and adding such thing on majority of RTL classes would be waste of time and effort.

I don't agree with this, but Embarcadero devs seem to agree, since they closed my ticket about it.

 

Share this post


Link to post
3 hours ago, Kas Ob. said:

It is not !, but wait what are we talking about ? is memory-safe in your phrase is the same as my above or in the articles ? the same perspective ?

I get your point, but it's maybe an issue of wrong usage of terms here.
When talking about memory-safety: Delphi is NOT
When talking about: system-vulnerability-safety (or the like): You could probably argue that it's better than C++, closer to behaviour as JS, but I doubt that too.

 

Share this post


Link to post
43 minutes ago, Rollo62 said:

I get your point, but it's maybe an issue of wrong usage of terms here.
When talking about memory-safety: Delphi is NOT
When talking about: system-vulnerability-safety (or the like): You could probably argue that it's better than C++, closer to behaviour as JS, but I doubt that too.

Its not that only.

 

See, we the Delphi programmers used to do things in specific way, this out of the structure of the language of Pascal and by tradition or best practices, it goes like (as example ) automatically without thinking to put try..finally then call free, C++ there is none like this, but i am not saying C++ is incapable of, on contrary it can do more things because it is more powerful, but C++ developers doesn't have the discipline of Pascal's, this is exactly why all these big companies with their top tier developer keep doing or falling with the same traps again and again.

 

When these big companies suggest to switch to different language like Rust not out of powerful of Rust or the lack of the tools in C++, on the contrary they reached to a conclusion that too much power is simply harmful, more limited tools are better fit and more secure.

 

When you say Delphi is not memory safe, yes it is, just like any other language, yet the guide lines for Pascal and Delphi are way simpler and clearer than C++ to produce memory safe code (either bugs or vulnerability) , Rust is similar, its guide lines are harder to break as they incorporated within the language syntax itself.

In Delphi if you leave the Overflow Check at on all the time, then you really had to be making big mistakes to breach memory safety for something like accessing index memory or handling managed types, these managed types specially arrays and strings are managed by the compiler in very nice way, in C++ there is hundreds of implementation of such arrays and strings, and they all will depends on some implementation, yet while they are completely safe at the same type coming form the same library, they are useless when it comes to interact with different library or the OS or whatever and here comes the problems of casting and unsafe converting.

  • Like 1

Share this post


Link to post

One more thing, if it was easy to define and put finger on memory safety issues in C++, then trust me, no one would have discussed memory safety at this scope and this range of popularity.

Each projects and each company has its own strict guide lines for safety and integrity of code, yet it is so clear that they are still short and still fail.

 

In movies they say the villain should be masterful without any mistakes every time, while the good detective need to be lucky once.

With security this rule is reversed the good guy should not make a simple mistake in thousands of code, and the villain need to be lucky to found one mistake.

 

Delphi/Pascal is easier to produce memory safe code and executables.

Share this post


Link to post
4 minutes ago, Kas Ob. said:

Delphi/Pascal is easier to produce memory safe code and executables.

I would agree that it is easier than using C++, among others.

 

But Delphi is also just as capable of generating executables that overwrite memory or have vulnerabilities, due to poor or improper memory handling. In that sense, I don't think Delphi has better memory safety than C++.

 

And certainly capable of being used to intentionally expose memory related vulnerabilities.

Share this post


Link to post
3 hours ago, EugeneK said:

All classes that take TComponent owner already need to be manually freed when passed nil as a parameter. There could be bugs because of double free/memory leak because of this too.

I think that you don't fully grasp the difference between forgetting to free an object instance which will cause a memory leak and accidentally triggering reference counting mechanism which will trigger premature destruction of an object which is still in use.

 

3 hours ago, EugeneK said:

Exactly! That's the whole point, it also has other advantages, like ability to provide different implementation for classes.

And TComponent seems to already implement interface reference counting, so maybe all that is needed to add interface implementing public methods.

For providing different implementation for classes by using interfaces, it is not enough to add interface to the class, you need to change all signatures from class to interface. This is not backward compatible. 

 

Also, TComponent does not implement reference counting, it is disabled for almost all use cases, and it works under very specific scenarios. Not to mention that TComponent is one of the main reasons why full ARC compiler was removed. It is completely incompatible with ARC. TXmlDocument is an outlier.

3 hours ago, EugeneK said:

You never really need automatically manage memory, you can always free it manually it just a big source of bugs. I think goal of compiler developers should be to give people options to avoid them and write simpler code. Just now I found 10 year old bug where TStrings object was assigned to already created object causing memory leak, this kind of bug is almost impossible to find and it would not be a problem if it was IStrings instead.

I beg to differ. Original code had a memory leak because of wrong assignment, but such leak is detectable and if you follow the leak you can find issue in the code. If you had IStrings, you would not have a leak, but you would still have a bug in your code because there is still a wrong assignment somewhere. Anything can be source of bugs, just the bugs and issues you have will be different. 

 

 

3 hours ago, EugeneK said:

For smart pointers I don't really see a way to use them as elegantly as interfaces, at least with current Delphi language.

 

https://github.com/dalijap/code-delphi-mm/blob/master/Part5/SmartPointer/Smart.dpr

 

procedure UseStrings(Strings: TStrings);
begin
  Writeln(Trim(Strings.Text));
end;

procedure SmartPtr;
var
  sl: ISmartPointer<TStringList>;
begin
  sl := TSmartPointer<TStringList>.Create();
  sl.Add('I am inside automanaged StringList');

  UseStrings(sl);
end; 

I think the above code is simple enough. The name SmartPointer is rather long and it can be easily shortened.

 

If you would want to have the same functionality as the above code with interfaces while preserving backward compatibility then you would have to write something like:

 

procedure UseStrings(Strings: TStrings);
begin
  Writeln(Trim(Strings.Text));
end;

procedure SmartPtr;
var
  sl: IStrings;
begin
  sl := TStringList.Create(auto);
  sl.Add('I am inside automanaged StringList');

  UseStrings(TStrings(sl));
end; 

Which also shows why you cannot insert different implementation as you need to typecast back to TStrings if you want to preserve backward compatibility.

 

4 hours ago, EugeneK said:

I don't agree with this, but Embarcadero devs seem to agree, since they closed my ticket about it.

 

I assume this is the ticket https://quality.embarcadero.com/browse/RSP-36609 I fully agree with the closure. Adding interfaces to TStrings for the sole purpose of having automatic memory management would only add burden to that class hierarchy while achieving nothing that cannot be done by smart pointers. What Bruneau Babet suggests is the right course of action, adding memory management from the within opens possibility for wrong usage and accidental errors. Using smart pointers (the examples from C++ and Rust are in line with above smart pointer example) is the way to go.

 

Now, there is no universal smart pointer support built in the RTL, adding that would be more meaningful and more versatile solution than adding interfaces to handpicked classes.

 

Share this post


Link to post

I don't believe their concern is memory leaks when they recommend using memory-safe languages, so I'm unsure what the focus of this conversation is.

Share this post


Link to post
Just now, Attila Kovacs said:

I don't believe their concern is memory leaks when they recommend using memory-safe languages, so I'm unsure what the focus of this conversation is.

Memory leaks as such are indeed not relevant for this discussion, but accessing invalid memory is the focus of this conversation and manual memory management opens up such possibility. 

Share this post


Link to post
13 hours ago, Kas Ob. said:

try..finally then call free, C++ there is none like this, but i am not saying C++ is incapable of, on contrary it can do more things because it is more powerful, but C++ developers doesn't have the discipline of Pascal's, this is exactly why all these big companies with their top tier developer keep doing or falling with the same traps again and again.

I would disagree, at least from my point of view.
I used try-catch in C++ on a regular base, even years ago, and find them even more flexible and more clear to use than try-finally-except.

Share this post


Link to post
2 hours ago, Rollo62 said:

I would disagree, at least from my point of view.
I used try-catch in C++ on a regular base, even years ago, and find them even more flexible and more clear to use than try-finally-except.

Fair and with in your right, but let me ask you a simple question 

 

When you last time saw Delphi/Pascal code where a function had one letter name like f or g ?... 

Yesterday i watched this 

I believe i pasted the link as Stefan put it in the German forum 

 

The talk is great and very valuable, and if anyone is not familiar with lecture then know that this dude wrote C++ specification for breakfast, and here it comes write the guide lines for safety, yet when i watched it i saw that he himself with his examples violate a rule that always use expressive naming, and yes there was f and g, this comes from math, and the obsession of C++ developer with math to look cool, everyone looks to Bjarne and his talks and books, yet the beginners will scratch these examples in their brains forever with one letter function as name.

 

Look at this "New Rules" titled in 2020

https://devblogs.microsoft.com/cppblog/new-safety-rules-in-c-core-check/

 

I think every C and C++ compiler out there does warn about default for a switch, yet that blog post deemed it a must to remind everyone with it, in Rust the code will not compile and C and C++ and in %90 no one will see it because there 458648567 another warning, some of these warnings makes sense but most of them don't, C and C++ are cursed with arrogance and stubbornness and its culture is beyond control, (my opinion)

 

Rollo62 all what i am saying is even with all of this power of C++, it fails be the best language for long term security and safety, they (the most invested companies and teams and i trust they have better insight and view on this subject ) said C/C++ will not cut it and Rust it is. they decided to burn the tower and throw the power tools for better language, that (again) doesn't bring any thing new, on the contrary only remove the ability to use many C++ features, and evidently they see it as success story.

  • Like 1

Share this post


Link to post
1 hour ago, Dalija Prasnikar said:

For providing different implementation for classes by using interfaces, it is not enough to add interface to the class, you need to change all signatures from class to interface. This is not backward compatible.

I meant in my own code, for example in unit tests sometimes it is easier to provide mock of some class rather than constructing it.

 

Quote

 

TXmlDocument is an outlier.

 

It is an outlier but it exists, which means it is possible, and I dread thinking what it would have been using it if it would not be interface based.

 

Quote

 

I beg to differ. Original code had a memory leak because of wrong assignment, but such leak is detectable and if you follow the leak you can find issue in the code. If you had IStrings, you would not have a leak, but you would still have a bug in your code because there is still a wrong assignment somewhere. Anything can be source of bugs, just the bugs and issues you have will be different.

Well in my case it would have been an innocent bug because it was assigned just after creating, so no information was lost, but application would have been working instead of shutting down every few days.
 

Quote

 

I think the above code is simple enough. The name SmartPointer is rather long and it can be easily shortened.

 

That's really nice, I wonder why they won't add something like this to RTL. But you agree that it is less readable than using interfaces.
 

Quote

 

Which also shows why you cannot insert different implementation as you need to typecast back to TStrings if you want to preserve backward compatibility.

 

But why would you want to typecast back to TStrings? By backwards compatible I meant that existing code won't break and if you need to use TStrings you just use continue to use TStrings as before, but in new code if you declare it as IStrings you can pass it to procedures that accept IStrings.

 

Quote

 

I assume this is the ticket https://quality.embarcadero.com/browse/RSP-36609 I fully agree with the closure. Adding interfaces to TStrings for the sole purpose of having automatic memory management would only add burden to that class hierarchy while achieving nothing that cannot be done by smart pointers. What Bruneau Babet suggests is the right course of action, adding memory management from the within opens possibility for wrong usage and accidental errors. Using smart pointers (the examples from C++ and Rust are in line with above smart pointer example) is the way to go.

 

Main purpose is separation of interface from implementation so you can use TMySuferfastStrings or TUnitTestThisClassStrings and your code won't need any changes, I guess I prefer way of C# where all collections are interfaced, rather than C++

 

Share this post


Link to post
Posted (edited)
4 hours ago, Kas Ob. said:

Rollo62 all what i am saying is even with all of this power of C++, it fails be the best language for long term security and safety, ...

Thanks for the links, but what made you think C++ fails to be the best language.
Only because you can do nearly everything you like, even things you shouldn't ?
I always state that you should better use only 80 % of such language possibilities and stay away from the latest cool hype stuff.

 

At least I would say that C++ is mature and rock-solid in any way.
To get back to try-except: The last time I learned about Pascal-vulnerabilities, it shook me and I understood many of the sporadic issues I saw in mobile development.
Thanks to Dalija's blog posts.

Not to be able to rely on exception catching the way I expect is breaking the foundations of my small, parallel world :classic_biggrin:

Unfortunately, I would not say that Delphi is superior to C++ in any way.

 

Edited by Rollo62

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×