Pointers can be still used in pascal and i think they may preserve it until delphi is alive.
Even though i have used pointer when i am learning pascal. I still can't understand the real use of pointers, I manage to do all my delphi programs without it.(by some other ways)
what is the real use of pointers. And I am asking for real world usage, and can we manage to do anything without pointers.
You use pointers a lot more often than you think you do in Delphi. The compiler just hides it.
var
SL: TStringList;
...
SL := TStringList.Create;
// SL is now a pointer to an instance of the TStringList class.
// You don't know it because the compiler handles dereferencing
// it, so you don't have to use SL^ . You can just use the var.
SL.Add('This is a string');
A string is also a pointer to a block of memory that stores the string. (It actually stores more than that, but...)
So are instances of records, PChars (which is a pointer to a character array, basically), and tons of other things you use every day. There are lots of pointers that aren't called Pointer. :)
the pointers contain the address of a memory location, because that are present everywhere. each variable which you declare, even the code which you write can be accessed using a pointer, the pointers is one of the most essential elements in Win32 programming, you must read this great article from Rudy Velthuis Addressing pointers to understand the pointers usage.
To understand what pointers might be used for in modern day Delphi, one needs to understand how pointers have been historically used and how Delphi uses pointers behind the scenes.
Pointers to code
One can have a pointer to a piece of code. This can be used for the intuitive thing (parameterizing some algorithm with the functions it needs to call; example: TObjectList.Sort takes a function pointer as a parameter). Modern Delphi uses pointers-to-code to implement the following (without going into details):
Virtual Method Tables; We can't have OOP without VMT's
Interfaces
Events and anonymous methods.
Those are all very powerful methods of avoiding raw pointers to code, indeed there's very little need for raw code pointers today.
Pointers to data
Everybody learned pointers using the Linked Lists. Pointers are essential in the implementation most non-trivial data structures; In fact it's hard to name a useful data structure that's not implemented using pointers.
Delphi gives lots of grate abstractions for data pointers, so we can work without ever touching an pointer. We have Objects (class instances) and good implementations for most data structures (string, TObjectList, dynamic arrays).
When do we use Pointers?
We essentially use pointers to implement more of the grate stuff that Delphi provides for us. I can give examples of what I've used pointers for, but I find it more interesting to give examples of what others have used pointers for:
TVirtualTree: Makes good use of pointers to data.
Pascal Script for Delphi: Makes extensive use of raw pointers to code!
Let's start with a definition, taken from Wikipedia:
A pointer is a programming language
data type whose value refers directly
to (or "points to") another value
stored elsewhere in the computer
memory using its address.
All computers address memory and to do so the machine language that they execute must do so using pointers.
However, high level languages do not need to include pointers explicitly. Some examples of those that do not are LISP, Java, C#, Perl, Python, but there are many more.
I'm interpreting your question to be why languages support explicit pointer use, since all languages use pointers implicitly.
Delphi descends from Pascal which is a rather primitive language when viewed from the 21st century. Pascal pointers are the only way to use references. In modern Pascal derivatives, e.g. Delphi, have many types of data that are reference based, but implicitly so. For example I'm thinking of strings, object instances, interfaces and so on.
It is perfectly possible to write any program in Delphi without resorting to explicit pointers. The modern trend away from explicit pointers is down to the observation that explicit pointer code is more prone to errors than the alternatives.
I don't think there's any real reason to carry on using explicit pointer code in Delphi. Perhaps very time critical algorithms may push you that way, but I'm really struggling to think of anything that is significantly better implemented with pointers than with the alternatives.
Personally I avoid using explicit pointers wherever feasible. It generally makes code easier to write, verify and maintain, in my experience.
1) Classes are pointers. Strings are pointers. The compiler pretty much hides this from you but you do need to understand this when debugging.
2) Any sort of tree structure needs pointers.
I use a lot of custom data structures in my programs (for instance, in my own scripting language /interpreter/, where I store the structures, or "records", used in this language - these can contain other records and the nesting is unrestricted). I do this at the very lowest level, namely, I allocate a number of bytes on the heap, and then I read, parse, and write to these completely manually. To this end, I need pointers to point to the bytes in the allocated blocks. Typically, the blocks consists of "records" that reference each other in some ways. In addition, many of these structures can be written to file (that is, I have also designed my own binary file formats), simply by copying from the heap (in RAM) to the disk byte-by-byte.
Pointers (memory addresses) are a basic CPU type to access memory. Whatever language you use to write an application, when it comes to the CPU it has to use "pointers" to work.
Thereby they are a low-level type which allows a huge degree of versatility, at the price of a somewhat more complex management and the risk of accessing or writing the wrong memory if not used correctly.
You could let a language translate your data to pointers and memory buffers, or use pointers directly if the language allows for it. Being able to do it allows for direct and optimized memory access and management.
I thought I could add my salt to the soup, but the answers above say it mostly all. There's one more thing though. I remember being scared when I saw all those referencing and dereferencing operators (in different languages) and all the magic that was done with pointers. I didn't dare to look the devil in the eye for YEARS. I preferred to ineffectively copy data instead of going down the pointer path.
Today though, I do love pointers. Working with pointers makes you aware of what happens under the hood. And it makes you aware of the memory you are playing with (responsibly). Practically it allows you to code more effitiently and consciously! Last but not least it turns out to be quite fun to play with such simple but powerful toys.
Related
As I understand it, when a managed language (like Haxe) can and wants to compiles to a non-managed language (like C++), it includes some form of garbage collector in the runtime.
I was wondering if it would be possible to completely abstract away memory management in the intermediate representation / abstract syntax tree, so that a garbage collector would not be needed and the default behavior (stack allocations live until end of scope and heap allocations live until freed) could be used?
Thank you!
If I understood you correctly, you're asking whether it's possible to take a garbage collected language and compile it to an equivalent program in a non-garbage collected language without introducing memory errors or leaks, just by adding frees in the right places (i.e. no reference counting or otherwise keeping track of references or implementing a garbage collection algorithm in anyway or doing anything else at run time that could be considered garbage collection).
No, that is not possible. To do something like this, you'd have to be able to statically answer the question "What's the point in the program, after which a given object is no longer referenced", which is a non-trivial semantic property and thus undecidable per Rice's theorem.
You could define a sufficiently restricted subset of the language (something like "only one live variable may hold a strong reference to an object at a time and anything else must use weak references"), but programming in that subset would be so different from programming in the original language¹ that there wouldn't be much of a point in doing that.
¹ And perhaps more importantly: it would be highly unlikely that existing code would conform to that subset. So if there's a compiler that can compile my code to efficient GC-free native code, but only if I completely re-write my code to fit an awkward subset of the language, why wouldn't I just re-write the project in Rust instead? Especially since interop with libraries that aren't written in the subset would probably be infeasible as well.
In Delphi we can do this:
interface
var
test: string = 'this is a test!'; { compiler accepts that }
But we can not do this:
implementation
procedure showTest;
var
internal_test1; { compiler accepts that }
internal_test2: string = 'another test'; { compiler error }
I hope some user from Embarcadero could answer that. :-)
Global variables' values are assigned from compile-time constant expressions, and they're stored in the program's data segment. That is, space for those variables is allocated physically in the EXE file, so when the OS loads the program, those variables are loaded implicitly. The compiler can ensure that those variables are initialized without executing any code at run time. It just stores their initial values in the EXE file.
Local variables, on the other hand, do not exist until run time. There is no physical space in the EXE that will always refer to those variables. To initialize them, the compiler would have to generate code to assign values to them.
Global variables can be initialized because it was a technically easy thing to implement in early compilers, and it's essentially a free feature at run time, requiring no execution of any instructions by the CPU.
If you want to initialize local variables, you're free to write the code yourself; that code can do exactly what any compiler-inserted code would do.
Niklaus Wirth was a Computer Scientist researching and teaching the design of Languages and Compilers. When he designed the Pascal Language and Compiler, some of his design goals were to make the compiler small fast and efficient, and to partition tasks so that the compiler did things that were easy for the compiler, and the programmer did things that were easy for the programmer.
In line with these goals, he designed a Single-Pass compiler, that only had to read the source code once, and understood everything the first time through. He also designed a compiler with a very simple state machine: everything is done in order, in correct order, only in correct order.
By doing so, he was able to easily get a very small, fast, efficient and correct compiler, in contrast to C compilers which were notoriously difficult, incorrect and inefficient, and FORTRAN compilers, which were slow and large.
Doing static constant allocation once, at the start of the program, is one of these design decisions that allows you to write a small, fast, efficient, correct compiler.
Decades ago, Borland wrote a Pascal compiler that was small, fast, efficient and correct, and it competed successfully again more expensive products from other companies (such as MS) that allowed out-of-order declarations and other generally useful and helpful options that made the compiler more slow and difficult, but made programming easier.
In other words, MS choose to partition the tasks between compiler and user differently than Borland/Wirth did.
And the MS Pascal compiler was dropped a very long time ago. But the Borland compiler continues as Delphi.
Computers are a lot faster now than they used to be, but the task of writing a small, fast, efficient, correct compiler remains the same. New features are not free. Adding complexity to compilation comes at a cost. Even a simple feature is messy if it has to be added as an exception to the way the whole compiler and language were designed right from the very beginning.
I am working a on parser which will go through a FASTMM4 memory leak report and store all relevant data in a custom-made structure/class. I use VirtualTreeView to display each class that has leaked instances as a node in the tree. The tree -
Notice that the FIRST node says unknown. This is because FASTMM calls a method AClass to determine weather it is a class or not. When it finds custom structures, it marks them as unknown, which doesn't make my report analyzer very effective since most memory leaks come from these custom structures and records.
Question: Is there a way to use DebugInfo or some other tool like JVCL to gather those debug symbols and compare their memory addresses to the ones found in the memory-leak-report-file? I would like my tree to stop showing UNKNOWN and show the names of these custom structures.
I am new to Delphi programming, and even newer to tackling memory leaks, so any help would mean much!
Maybe extended RTTI (Delphi 2010 an newer) can be used to create a type dictionary, which only holds typeinfo pointers and names of all "non-class" types.
This feature could be enabled with a conditional define to avoid its overhead in normal operation.
My superficial understanding of variables in f# suggests that declaring a variable to be 'mutable' and using a 'ref' variable essentially both do the same thing. They are both different ways to address the same underlying issue - a limited and structured allowance of mutability in a functional language without having to resort to the IO Monad. That there is a technical different has been 'abstracted' by my understanding.
If this is the case why can't closures capture mutable variables, but they can capture ref instances?
More generally, what is the technical different between the two forms that allows this difference?
What is the purpose from a language design point of view of introducing two mutability shortcuts rather than just one?
I'm sorry if this is a multi-parter, but they all seem related.
See
http://lorgonblog.wordpress.com/2008/11/12/on-lambdas-capture-and-mutability/
especially the "language design commentary" section (I'd quote it here, but it doesn't stand alone well, you need the whole blog entry for context).
What is "tagged memory" and how does it help in reducing program size?
You may be referring to a tagged union, or more specifically a hardware implementation like the tagged architecture used in LISP machines. Basically a method for storing data with type information.
In a LISP machine, this was done in-memory by using a longer word length and using some of the extra bits to store type information. Handling and checking of tags was done implicitly in hardware.
For a type-safe C++ implementation, see boost:variant.
Not sure, but it is possible that you are referring to garbage collection, which is the process of automatically disposing of no longer used objects created when running a program.
"Tagged memory" can be a synonym for mark-and-sweep, which is the most basic way to implement garbage collection.
If this is all wrong, please edit your question to clarify.
The Windows DDK makes use of "pool tags" when allocating memory out of the kernel page pool. It costs 4 bytes of memory per allocation, but allows you to label (i.e. tag) portions of kernel memory which might help with debugging and detecting memory leaks.
BTW I don't see how anything called "tagged memory" could reduce program code size. It sounds like extra work, which translates to "more code" and "bigger program." Maybe it's meant to reduce the memory footprint somehow?
Here's a more technical description going into the implementation details as to how this is used for garbage collection. You may also want to check out the wikipedia article about Tagged Pointers.