Тёмный

Is there Garbage Collection in C and C++? 

Jacob Sorber
Подписаться 157 тыс.
Просмотров 32 тыс.
50% 1

Patreon ➤ / jacobsorber
Courses ➤ jacobsorber.thinkific.com
Website ➤ www.jacobsorber.com
---
Is there Garbage Collection in C and C++? // You aren't the first person to wonder about automatic memory cleanup in C. Why don't we have garbage collectors like they do in other languages? Let's talk about it.
Related Videos:
Memory Issues playlist: • Memory Issues
***
Welcome! I post videos that help you learn to program and become a more confident software developer. I cover beginner-to-advanced systems topics ranging from network programming, threads, processes, operating systems, embedded systems and others. My goal is to help you get under-the-hood and better understand how computers work and how you can use them to become stronger students and more capable professional developers.
About me: I'm a computer scientist, electrical engineer, researcher, and teacher. I specialize in embedded systems, mobile computing, sensor networks, and the Internet of Things. I teach systems and networking courses at Clemson University, where I also lead the PERSIST research lab.
More about me and what I do:
www.jacobsorber.com
people.cs.clemson.edu/~jsorber/
persist.cs.clemson.edu/
To Support the Channel:
+ like, subscribe, spread the word
+ contribute via Patreon --- [ / jacobsorber ]
Source code is also available to Patreon supporters. --- [jsorber-youtube-source.heroku...]

Опубликовано:

 

27 июн 2022

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 150   
@FintasticMan
@FintasticMan Год назад
Technically C++ versions from C++11 up to and including C++20 have reachability-based garbage collection and leak detection specified in the standard, but no compilers have ever implemented it. It is going to be removed in C++23.
@benjaminshinar9509
@benjaminshinar9509 Год назад
episode 256 of c++Weekly is about this topic.
@Minty_Meeo
@Minty_Meeo Год назад
This comment and reply are better answers than the actual video.
@raymundhofmann7661
@raymundhofmann7661 Год назад
Back when they worked on C++11 they probably thought garbage collection in Java is a thing and a major reason why C++ got a bit neglected since year 2000, but thank god this garbage is out of the standard now. Moore's law not quite applying to single core performance anymore and battery powered devices trying to keep the battery as small as possible and runtime as long as possible limited the hybris of all these garbage language disciples and restored the interest in C++. Now it can be said that languages that have garbage collection and no manual control over it are often garbage and create garbage, meaning they consume around 10x to 100x of the memory and also too much CPU compared to what a good program with deterministic memory management would and this is very hard to change significantly.
@greg4367
@greg4367 Год назад
Re Removal. The sooner the better the faster
@EvilSapphireR
@EvilSapphireR Год назад
CPP does call an objects destructor once it goes out of scope, so you can write memory freeing logic in the destructor.
@ShadowaOsu
@ShadowaOsu Год назад
that is only if you initialize the object on the stack this doesn't happen if you allocate memory from heap the best you can do is to wrap an heap allocated object within a class and initialize that class' instance on the stack, then free the heap memory in that class' destructor but that's already done by the std library and are called shared/unique pointer classes
@SurenEnfiajyan
@SurenEnfiajyan Год назад
@@ShadowaOsu Try to avoid working with raw pointers and mem allocations/deallocations as much as possible, and use safe data structures (for example STL containers) or at least encapsulate the pointer logic in classes.
@ShadowaOsu
@ShadowaOsu Год назад
@@SurenEnfiajyan thank you for the great advice, I'm also aware of idioms of C++ and actively following and using modern C++ features. I just want to clarify the original comment.
@h-0058
@h-0058 Год назад
This is exactly what smart pointers do. Take a look at std::unique_ptr (which is the most used) and std::shared_ptr (perfectly explained by the reference count thingy in the video, but not as used, since unique pointers do the same thing, just that you cannot have more than 1 pointer pointing to that block). All of this assumes that you don't specifically mess around with the language, because in C++ you can easily do whatever you want, but using a smart pointer for example and then also having a raw pointer to the same block is just shooting yourself in the foot.
@raymundhofmann7661
@raymundhofmann7661 Год назад
And with move semantics you can conveniently transfer a object between scopes and the scope where it ends up will do the final destruction of the in this scope non moved object. This is not only convenient for memory management, it is for other resource handling or to conveniently handle program state, esp with multi threaded or co-routine programming. Do that in Javascript or another garbage language, you will feel like having to manually manage memory with C malloc and free only. The scoped object lifetime concept extended with move semantics recently really is a benefit garbage languages don't have.
@Ba-gb4br
@Ba-gb4br Год назад
C an C++ are low level languages where you have (almost) total control. Once you add a memeory garbage collector to a language you lose a bit of control because the garbage collector decides when memory is freed. This opens the door for many other problems concerning performance, predictability, etc.
@erick_falker
@erick_falker Год назад
I never had to worry about memory leaks anymore since I started using std::unique_ptr and std::shared_ptr. These two classes release the burden on the programmer about managing the heap allocated memory.
@oscareriksson9414
@oscareriksson9414 Год назад
You could also grab a chunk of memory and store your things there. This way you can implement any data structure you'd like. It could be stack, queue, array, list and so on. This will also take away the memory leak issue since you can easily reset and reuse that memory. Since I started doing memory arenas I don't even use new-delete or malloc-free any more. Sure you need to implement the arena or data structure thingy at least once and maybe you can't be bothered with that. Lucky for me I like doing that sort of thing so it's a win-win for me personally
@mikeyangyang8816
@mikeyangyang8816 Год назад
Smart pointers are great, but just beware the pit falls. Both shared_ptr and unique_ptr are slower to access than raw pointers. I have only tested on shared_ptr. I allocated few arrays of objects dynamically using make_ptr, and the program runs extremely slowly. I then profiled the code using visual studio, which showed exactly shared_ptr access is using around 85% ~ 90% of the cpu epochs. Which is just insane, and I just skipped on unique_ptr and just used new/delete raw pointers, which uses almost zero cpu epochs. I know for most cases, this kind of performance makes little difference (ie. if you are doing disk read/write then using shared_ptr will not be the bottleneck). So, I think people should use smart pointers during development/feature testing, then switch to raw pointers when shipping. Since you have finalized the code, deleting it wouldn't be a big guesswork.
@ShadowaOsu
@ShadowaOsu 4 месяца назад
@@mikeyangyang8816 actually, unique_ptr has the same exact performance with raw pointers when optimizations are enabled. shared_ptr has this performance problem because internally, it uses reference counting to keep track of how many pointers refer to a resource (because it's shared) There can also be reference cycles so there's also that to be careful about. unique_ptr on the other hand, doesn't have these problems since it is not copyable (hence, unique). So because of the issues like you pointed out, using shared_ptr is questionable but I suggest using unique_ptr to manage dynamically allocated objects when ever possible
@mazdakhng3013
@mazdakhng3013 Год назад
smart pointers in cpp do this job quite efficient and fast. I haven't seen any performance bottleneck.
@benhetland576
@benhetland576 Год назад
Smart pointers don't do garbage collection. They just help avoiding creating the garbage in the first place.
@tordjarv3802
@tordjarv3802 Год назад
While I think smart pointers should be used when ever possible I think it is necessary to keep in mind that there are valid situations where you simply can't. For example, if you for some reason need to use a library that is written with raw pointers (could be simply a requirement from your employer or customer to use a specific library). While you could use smart pointers when not dealing with that library using smart pointers when doing so could lead to unwanted double frees if the smart pointer deallocates while the legacy library still holds a reference. Lastly I have encountered situations where I have noticed significant overhead with smart pointers, but they are rare.
@benhetland576
@benhetland576 Год назад
@@tordjarv3802 Also, if the library allocates, then the library should do the deallocation. There is no guarantee that the library uses the same memory allocator that the caller does, e.g. a DLL compiled with a different compiler and/or runtime library.
@mazdakhng3013
@mazdakhng3013 Год назад
@@tordjarv3802Yes, correct, it cannot be used always. About legacy libraries we sometimes wrap them into a class and use smart pointers also. About performance, actually every single time that we ran into a problem, we finally found out that it was our problem, for not using weak, unique, shared one in proper place.
@Leonhart_93
@Leonhart_93 Месяц назад
​ @benhetland576 Shared pointers do the same thing as garbage collectors: reference counting. But it's a localized behavior.
@code8986
@code8986 Год назад
Your videos are consistently among the absolute best tutorials on C/C++ that I've ever seen on RU-vid. I have a lot of experience in garbage-collected languages (e.g. C# and Java) but not any in unmanaged languages, so I'm slowly teaching myself C (and C++, later), in large part through your videos. Thank you for sharing your knowledge.
@JDahl-sj5lk
@JDahl-sj5lk Год назад
If you want garbage collection is C++ just use smart pointers; ex unique ptr. Objects on the stack are freed automatically, and f.ex unique_ptr is basically an object wrapper that Will auto free memory thru its destructor. But the point of not having garbage collection is that sometimes you really dont want it, f.ex; you might want to run a function loading textures (and pointers to them) and you do not want them to go out of scope before you explicitly say they are. And when you do want heap allocs that are auto freed, f.ex a map/list/Vector of heap objects then you can just use unique ptrs, which also can help you a little since they will give you compiler errors if the object in question is moved or copied implicitly, which can easily happen especially with vectors. The error msgs might not be great, but usually Will let you know there is something wrong with how you manage your unique ptrs which often means you have copied/moved them. F.ex a Vector of unique ptrs to objects of class Example; std::vectorMyObjects; Now if you push to that Vector, and then push again, the Vector Will move objects since it Will resize itself. That Will cause a compiler error. You can fix that by using std::move when pushing, or make a move ctor for class Example. It is a bit much to take in at first, but you do get used to it, and onxe you do, understand memory layout and the internals of the std template library all the better.
@DenisovichDev
@DenisovichDev Год назад
Great video as always Jacob.
@HairyPixels
@HairyPixels Год назад
In C++ smart pointers are close enough to garbage collecting but they need to be opted in to manually and have some friction involved with them. In C try making memory pools. Bottom line is if you're using either C++ or C you probably care about performance and in most cases manually freeing memory helps you think about the memory layout of your program which is what you want anyways.
@martinprochazka3714
@martinprochazka3714 Год назад
And that the great thing about C++. You don't pay for what you don't use. In Java you might decide that GC is unnecessary overhead, you do the math and conclude that with your dataset you won't ever run out of memory if you leak everything but JVM be like "we don't do that here'.
@soniablanche5672
@soniablanche5672 4 месяца назад
not really, smart pointers are there so that you don't forget to write "delete" at the end of the scope. They aren't as sophisticated as real garbage collectors. In fact, sometimes it's better to not free memory when you are doing CPU intensive task because freeing memory is actually costly. A good garbage collector should detect when is the best time to free the memory.
@letsplaychannel6276
@letsplaychannel6276 6 дней назад
@@martinprochazka3714 You can actually change gc behaviour
@Christian-bc2my
@Christian-bc2my Месяц назад
What was being described here was reference counting GC, and it is in widespread and common use in C++. Not least on Windows, where it forms the core of the object lifecycle management of COM. But smart pointers are also a form of garbage collection. What C++ tends not to have is mark/sweep garbage collection. But there are libraries that do mark and sweep garbage collection in C/C++: en.wikipedia.org/wiki/Boehm_garbage_collector
@matheusdemoraes6322
@matheusdemoraes6322 Год назад
I've started to learn C language focused on development of softwares for embedded systems. I've have already some experience in programming for scientific computing and machine learning algorithms purposes. So, this content has helped me a lot. Thank you, I wish success for you.
@boblake2340
@boblake2340 Год назад
You are a superb teacher.
@cipherxen2
@cipherxen2 Год назад
I've created one library for this. It had a wrapper class to encapsulate pointer, it never exposes pointer to outer world, it just allows to interact with the object referred by the pointer. It can reference count and garbage collect automatically. It has one problem though, with circular references.
@leokiller123able
@leokiller123able Год назад
you could use `__attribute__((cleanup(cleanup_function)))` in front of the declaration of your variables to call `cleanup_function` on it when the variable gets out of scope, but you have to initialize that variable or else it's undefined behavior, and you can also use `__attribute__((destructor))` on a function for it to be automatically called after main
@kelvintakyi-bobi3155
@kelvintakyi-bobi3155 Год назад
You just blew my mind! 🤯
@yjc149
@yjc149 Год назад
you are the rockstar programmer, learned lot things from you. thanks again!.
@3bdo3id
@3bdo3id 2 дня назад
Great video as usual, thank you!
@JacobSorber
@JacobSorber День назад
Glad you enjoyed it!
@nunyobiznez875
@nunyobiznez875 Год назад
What about the Boehm-Demers-Weiser garbage collector? I read through some of the documentation some time ago, mostly out of curiosity. I've kept it in the back of my mind, just in case I ever felt the need for garbage collection with something, but I've never used it or needed it for anything. Still, it sounded promising, from what I remember reading of it. It basically works by replacing the call to malloc. I believe it's been around for a while and is the most noteworthy gc for C, though I have no idea how well of a job it actually does.
@raymundhofmann7661
@raymundhofmann7661 Год назад
It surely will bloat the memory use ten times, in average.
@ZEdixchannel
@ZEdixchannel Год назад
std::unique_ptr and std::shared_ptr in C++ are solving the garbage collection problem
@SurenEnfiajyan
@SurenEnfiajyan Год назад
Only that garbage collectors usually don't work immediately after the resource becomes unreachable, also they can deal with cyclic references.
@billbez7465
@billbez7465 Год назад
I am interested in memory management, but appreciate that there is a performance cost. To paraphrase Scott Meyer, "there are many applications where you simply cannot run fast enough". Such as game graphics, numerical simulation, stock trading, ....am I sure there are many others. I think this is why native languages such as C & C++ will never lose popularity. That is why I always want to become proficient in an managed language and a native language with no memory management. Thank you for the insightful video.
@marcossidoruk8033
@marcossidoruk8033 Год назад
C++ will lose popularity tho as it is a terrible language
@marcossidoruk8033
@marcossidoruk8033 Год назад
C++ will lose popularity tho as it is a terrible language
@jorgeferreira6727
@jorgeferreira6727 Год назад
@@marcossidoruk8033 What so terrible about it? C/C++ are probably the most powerful and versatile programming languages out there. Maybe some people just can't handle all that power.
@marcossidoruk8033
@marcossidoruk8033 Год назад
@@jorgeferreira6727 I love C, I hate C++. I agree that C/C++ are the most versatile programming languages out there, but that doesn't mean they are perfect, they def can be improved, thats why C++ was created, to improve on C. The problem is that it utterly failed and it doesn't deliver in anything it promises to do better than C. C is probably the perfect language for really low level stuff tho, the problem is that when doing some higher level stuff you may want to add abstractions for purposes of memory and thread safety mainly, the C++ way of Doing abstractions is absolutely not the way foward, C++ abstractions don't really abstract much, they are merely just wrappers of C functions that force you to do everything through overly verbose APIs that have tons of implicit behaviour, It kills one of the greatest advantages of C, that is no matter how complicated your code gets everything is pretty much explicitly stated on the code, that and the focus on the procedural paradigm creates readable code. C++ code is everything but readable, that why people use C for infrastructure and always will unless someone comes up with a language that does what C++ was supposed to do but better, Rust is promising in this respect.
@paivacn08
@paivacn08 Год назад
As C++ has destructors, you can implement smart pointers, and it was already done (std::shared_ptr and family). The real problem with C is that there is not a destructor (or drop function).
@marcossidoruk8033
@marcossidoruk8033 Год назад
You don't need that. Destructors and delete and so forth are just free() wrappers.
@zytr0x108
@zytr0x108 Год назад
@@marcossidoruk8033 but you have to remember all the time to call free()
@marcossidoruk8033
@marcossidoruk8033 Год назад
@@zytr0x108 And? In C++ you have to keep track of all the implicit code running, C just makes it explicit.
@zytr0x108
@zytr0x108 Год назад
@@marcossidoruk8033 Im not saying C++ is better. I like C, it has less confusing abstractions. But it’s true that C++ is less prone to memory leaks due to the dev forgetting a free()
@soniablanche5672
@soniablanche5672 4 месяца назад
In C, you typically would have a cleaning function that does both the freeing and whatever goes into the destructor in C++. The user would have to call "myDataStructure_free" instead of the regular "free". In fact, you would probably also have a constructor function instead of having the user call malloc manually.
@kwan3217
@kwan3217 Год назад
Garbage collection (or in general not leaking memory) is like cleaning up your room. Sure, you should keep your room clean all the time, but what's the point of spending effort cleaning if you know your house is going to be demolished tomorrow?
@benhetland576
@benhetland576 Год назад
Great analogy. With certain (pseudo) operating systems though, it was crucial to get this right as they did not "clean up the demolished site" afterwards, so to speak. Windows 3.1 springs to mind as notorious for this, as its resource handles that it used to keep track of such (files, windows, memory, everything...), or not, was a quite limited pool of resourses, and it crashes whenever it ran out of them. Now, one can argue that modern OSes don't suffer from this weakness, but in many contexts there still may not be any memory manager and/or virtual memory, such as on many small embedded systems that are becoming ever more ubiquious, and then it matters :-)
@raymundhofmann7661
@raymundhofmann7661 Год назад
But Jordan Peterson says you better clean up your room instead of having to demolish your house a few times a week.
@Minty_Meeo
@Minty_Meeo Год назад
In Pikmin (and many other GCN titles, I suspect), free and operator delete do literally nothing, since the game never needs it. It just throws out the entire primary heap when a scene change occurs. There is even a smart pointer implementation (remember, C++98 here) which I'm pretty sure had all of its logic gutted.
@redcrafterlppa303
@redcrafterlppa303 Год назад
For those looking for a garbage collection implementation for c++ take a look at Microsoft c++CLR (Common Language Runtime) it comes with the benefit that much of the .NET Framework(know from languages like c#, f# visual basic...) is already compatible with the garbage collection system implemented in c++CLR
@foomoo1088
@foomoo1088 Год назад
Wow, a lot to clarify IMO from this video! 1. C and C++ are so different it’s difficult to address both in these topics simultaneously 2. C++ DOES have managed pointers available (std::shared_ptr etc.) and a whole complex system with ref counters and move semantics… it’s not really garbage collection in sense of C# and other languages (e.g. you’ll need to take care to avoid circular references yourself!) and no reachability (mark and sweep) mechanism is running “collection” passes. But it does provide some ability to allow programmers to implement code without carefully keeping track of everything. 3. Of course you can write your own garbage collection in C++/C . You have power and flexibility in these languages and that is a feature of the language. With power comes responsibility. For example, Casting scenarios mentioned in this video are common in the lower levels of game engines as well as use of pointer arithmetic to move a pointer to the next address of a contiguous memory array of objects (though a hard coded +68 would be strange to see in code, but not clear how that slide in this video is relevant) 4. Many C++ Game Engines implement garbage collection. Check out Unreal Engine for example. The spirit of comments in the video indicate that people have “tried” , but not succeeded. These game engine implementations have shipped hundreds if not thousand so of games. Bottom line, C/C++ do not have garbage collection systems built into the language like C# , Java, etc. But C++ does have ref counted smart pointers. If you want a full garbage collection system of course you can build it yourself.
@lhpl
@lhpl Год назад
Nice to hear what you said around 2:30. I see that question often in various forums, so it must be a very common misunderstanding. Why it isn't obvious to some people that the OS will reclaim all memory at program termination really puzzles me. Back in my CP/M days, the way to exit could simply be a jump to address 0, which would result in a reboot of the system. I often think that the use of C++ with it's destructors, that 'must' be called, is causing anmoying problems, especially with large interactive graphical interface programs, in short: web browsers. I like to have my browser open at all times, I use many windows, and many tabs in each, I don't reboot my machime for months, and don't quit the browser unless the machine gets bogged down, which seems to happen more often over time. I use Firefox, because although Chrome may be a great browser, it doesn't seem to handle my usage pattern well. Firefox isn't perfect either, but at least it's better. Except when I decide it is leaking too much and needs a restart. I work on Linux, eith 8GiB RAM and just as much swap. But when it begins to use a good amount of swap, and I decide it's time, it takes an eternity for all the processes to quit. I guess it is because all parts of memory need to be swapped in for access just to run the destructors. This takes more than 10-15 minutes sometimes! If I just kill it, I suppose I run a little risk of having the persistent data messed up. I just wish someone would teach programmers to persist any data (sessions, state etc) whenever possible and respond to a quit command by just calling exit right there and then, instead of returning all the way back to main, wasting _my_ time running futile destructors on gigabytes of objects along the way. If the program also did a check in the event loop that no more memory is being used than before (except for new tabs and windows), and that inactive windows are paused and have their state persisted and flushed until reactivated, I think things would work a _lot_ smoother, using just a fraction of the memory. Maybe programmers should just be forced to program on machines with less memory for some time...
@anon_y_mousse
@anon_y_mousse Год назад
I agree, and I too use FireFox over Chrome. The problem of freeing memory at program exit is because in the old days the OS didn't free it. I've heard it claimed that Win98 did, but as a regular user back in the late 90's early 00's, I can safely say that is a lie. If they just allocated everything from one source and you're on a good OS, I'd say yeah, just save state and quit, but freeing memory shouldn't take gobs of time regardless of how the program exits and that sounds like a bug really. Do you also use multiple desktops/workspaces and have multiple windows open? I usually have at least 20 if not 30 things open, terminals, web browsers and a media player sometimes.
@lhpl
@lhpl Год назад
@@anon_y_mousse I've never programmed on DOS or Windows, but I can't imagine that they worked any different. On the Mac, system 6.0.5 got cooperative multitasking with MultiFinder, and then you had to specify a minimum and maximum memory which was then allocated to a process, up to the max. Upon exit the OS reclaimed the memory, and I doubt there has ever been a system that worked differently. (Things like TSRs of course being something different. And I don't know if the OS could leak itself, although I doubt it.) It's a great pity that Linux distributions are filled with daemons and user programs that are not always written with enough care, so you can have for example X or a window manager leak over time. I just switched away from Linux Mint Debian Edition because I sometimes saw the cinnamon process grow unreasonably. Anything that runs "perpetually" should have a defined maximal memory use, and there should be as few as possible. Why run an entire daemon just to check if there are new updates to the OS - that's a job for a cron task!? Yes. 20-30 windows are not unusual, one Firefox session O am using at the moment has so many, that the XFCE4 panel "app dock" (can't remember its name) can't show them all with the display height, but the designers apparently haven't anticipated this, as the drop down windows menu doesn't have a scrollbar... - which is also annoying.
@user-mr3mf8lo7y
@user-mr3mf8lo7y Год назад
Much obliged.
@voncheeseburger
@voncheeseburger Год назад
in systems programming your memory is normally freed by the battery running out or the mains cable being unplugged
@georgecop9538
@georgecop9538 Год назад
for c, you can use the dlsym trick and make a malloc tracker. In c++ put a delete statement in destructor and you should be ok.
@JacobSorber
@JacobSorber Год назад
Absolutely. Yes, you can track mallocs, frees, news, and deletes, but as long as you can't ensure that you know where all the references are, it's tricky to do any sort of automatic garbage collection. Adding delete's to destructors is still explicit memory management.
@crusaderanimation6967
@crusaderanimation6967 Год назад
7:17 Well techincly in modercn c++ compilers there are smart pointers with(while not garbage collected in literal sense) act as if there were garbage collected.
@thomasgebert6119
@thomasgebert6119 9 месяцев назад
I remember Walter Bright (the creator of the "D" language, as well as the Digital Mars C++ compiler) posted something awhile ago about how they got rid of all the "cleanup" code in their compilers for one basic reason: compilers are short-lived, and typically don't take a lot of memory anyway, so why not just malloc to your hearts content and let the kernel worry about cleanup afterwards? His argument is that Linux/Windows/MacOS is going to clean all the memory once you're done with the process anyway, so there was really no reason to bother writing "free" anywhere. He claimed that the code actually went substantially faster after that, and I'm inclined to believe him.
@cgerman
@cgerman Год назад
The other reason is that garbage collectors run whenever they decide it's time to do so, this is a dealbreaker in real-time applications because you can't have the garbage collector run when a function needs to run at most for X milliseconds otherwise you break the contract. In C and C++ you know exactly when memory will be released. After C++11 and the introduction of smart pointers you can really avoid a lot of manual work and you feel that you are writing with a garbage collector on standby.
@riscaverse
@riscaverse Год назад
Do you have a list of C books you like? Thank you for the great content!!!
@randomscribblings
@randomscribblings Год назад
So... it's worth noting that several implementations of Python (including the canonical) are in C. Java is self-hosted (Java is written in java). C is self-hosted (C is written in C). But Python is not written in Python. The canonical Python is even called C-Python to distinguish it from (say) Iron Python or JPython. So... that means that Python is an example of a Garbage collection written in C. It uses (as you did touch on) conventions to enforce Garbage Collection, but if you like Python and C, one of the contracts you will take (assuming to follow the directions) is the life-cycle of Python objects w.r.t. C code you link in. I believe there is also guidance on the life cycle of resources your C code manages. Sometimes I lament that the first thing covered in learning languages is not the "isomorphism" concept --- the idea that languages map one domain to another. This is as true for "English" and "French" (mapping between human thought and a representation that can be communicated to different humans) as it is for C and Python ... which map between an expression between our ideas and intentions (as best we can express and manage them) and what a computer can be encouraged to understand and/or translate. As such, a Python program _is_ a C program ... in this case ... in a way that a Java program is not... (unless a suitable and conformant implementation of java in C exists ... in which case, my bad)... I do recall programming on the Amiga where one needed to allocate "chip" memory with the OS allocation. The C library did clean up things malloc() and friends allocated, but you would leak memory if you didn't clean up your OS allocations. I would assume that arduino's and whatnot ... you'd either have the "long running" problem ... or the small OS problem ... so there may be modern common environments where cleaning up is still important.
@vercolit
@vercolit Год назад
Isn't the JVM written in C?
@muadrico
@muadrico Год назад
@@vercolit Yes, at least partially. Otherwise how would the JVM run if it needs a JVM to run, which would be the case if it would be written purely in Java.
@randomscribblings
@randomscribblings Год назад
@@vercolit I haven't just looked it up, but when you build a jvm in FreeBSD, you need to "bootstrap" it --- meaning you have to have a JVM to build a JVM. So I assume no. How do you bootstrap on a new platform, you might say? (I'm actually involved in the FreeBSD port to RISC-V, so I'll comment). The general answer is that you build a cross compiler --- a compiler on a working platform to produce binaries for your new platform. Then, in a 2nd step you build the new platforms actual (self-hosted) compiler. Then you're going to ask ... how do you build the first compiler? That varies. Often you build a rudimentary compiler in another language, or you use a platform like LLVM ... but now I'm getting into the weeds.
@sledgex9
@sledgex9 Год назад
You can get some semblance of "garbage collection" with smart pointers. They are builtin in C++11. In C you have to use a library eg gtk/glib.
@MAP233224
@MAP233224 Год назад
Hey Jacob I've been watching/listening to your vids for a while now and I can't seem to understand what kind of microphone setup you're using that makes you sound so distant and not uniformly leveled at all? It's a really weird audio experience tbh lol.
@FreeDomSy-nk9ue
@FreeDomSy-nk9ue Год назад
I'm shocked you did not mention smart pointers and the huge problem they solve. I'm still a raw pointers fan though
@SpeedingFlare
@SpeedingFlare Год назад
I feel like C++ RAII is needed to accomplish this
@ivanmoren3643
@ivanmoren3643 Год назад
Hi Jacob! On this topic I've been thinking about how C compilers and language standards still doesn't have the option to treat `dataptr.field` as `(*dataptr).field` automatically where the type of dataptr is known to be a pointer to a struct. Tsoding Daily recently made a proof-of-concept patch to tinycc implementing this (in the video "Hacking C compiler", patch shown at 1:50:00), and I think the question he is asking is reasonable: How much legacy code would *actually* be be rendered unusable by such an addition to the C syntax? It would be interesting to hear your take on it, OR even see you implement a similar patch in GCC, exploring the topic of backward compatibility through practical examples along the way (or, if everything just builds fine, talk about how the C language standard is developed and how a change can be "proposed" by introducing a change like this as an extension to the GNU-C flavour for example?). Hugs!
@benhetland576
@benhetland576 Год назад
In a strict C context it might work, but it would break the correspondence between what you type and what the compiler is doing, which I think is quite valuable in C. For instance you need to explicitly send a reference to a function parameter by taking its address (&) in order to get something returned into that variable. This is in contrast to C++ where there are references that can hide this contrast to the unwary, and there are also at lot of other things happening automatically behind the scenes (calling dtor for instance). In C++ one must also consider the fact that the -> * and ->* can all be overridden while the . and .* cannot. There have been cases that I have found myself having to write (*foo).bar instead of foo->bar with stuff like custom iterators and "smart" pointer implementations. Also consider: if the struct field in question is itself a pointer, what would the meaning of (*dataptr).field become? Would it mean dataptr->field or *(dataptr->field) then?
@somebodystealsmyname
@somebodystealsmyname Год назад
SerenityOS uses reference couting in a lot of places but now decided to switch to a memory safe language in the future.
@robertkiestov3734
@robertkiestov3734 Год назад
Sad to hear it’s becoming trans.
@greg4367
@greg4367 Год назад
Here is what 55 years of programming taught me: People who learn to code in assembly first, then C, would NEVER ask such a question in the first place. Further, if you learn to "program" in a "safe" language, you will NEVER write an operating system. Languages that "protect" you also keep you so very ignorant of HOW THINGS WORK!
@bobby9568
@bobby9568 Год назад
Do you have a reference or book recommendation?
@yooyo3d
@yooyo3d Год назад
Absolutely! Best comment about programming.
@bobby9568
@bobby9568 Год назад
Is that what you've learnt in life? If you'd go back in time you wouldn't enjoy life more by going outside?
@xniyana9956
@xniyana9956 Год назад
Ain't this the truth. I grew up in BASIC and never touched C and Assembly until much much later in life. These languages opened my eyes to a world I never knew existed.
@krunkle5136
@krunkle5136 Год назад
Totally agree. Similar to this I think is the mentality that low level isn't necessary because computers are fast enough it doesn't matter. There's a trade off, but there's value in keeping programs cheap to run, even if it doesn't produce an immediate effect. It's good just in case.
@shawnmichaels5484
@shawnmichaels5484 Год назад
Hey Jacob, Can you make a video on creating device drivers for linux? Thanks :)
@TheS1l3ntOne
@TheS1l3ntOne Год назад
Sir, What about cpp? Like there's std::shared_ptr and unique_ptr. How do they work? Can you make a video about that?
@viacheslav1392
@viacheslav1392 Год назад
6:19 actually language does not allow this... You can do pointers arithmetic until the resulting pointer points to the same object in memory, else it is UB. UB does mean that the language allows it....
@sinom
@sinom Год назад
RAII + smart pointers take care of garbage collection for you so you don't really need GC in C++ Edit: I expected it to at least be mentioned in this video... Come on.
@chriskleeblatt1867
@chriskleeblatt1867 9 месяцев назад
But than how does "free" know how many bytes it has to free if we are just giving it a single pointer?
@rhythmmandal3377
@rhythmmandal3377 Год назад
As student started with c it felt weird to have Garbage collection at first.
@dmitripogosian5084
@dmitripogosian5084 Год назад
It is still weird to me, but I do only scientific programming
@thebrowhodoesntlift9613
@thebrowhodoesntlift9613 Год назад
Speaking of memory... Is there a way to integrate the concepts of ownership and borrowing into c (like in rust)? If not then... why not?
@xniyana9956
@xniyana9956 Год назад
Ownership and borrowing are enforced entirely by the compiler in Rust. What this means is that you could technically do it yourself in C by observing the exact same discipline when writing your code. The only difference would be that the C compiler won't be there to complain when you choose to not adhere to the discipline.
@casperes0912
@casperes0912 Год назад
Just started video, but I'll say this is about the stack and }
@generessler6282
@generessler6282 Год назад
Basically good info, but several sins of omission. First, reference counting is only one kind of GC. There's mark and sweep and copying GC for a couple of other examples. Second, long-running apps are not the only ones that need GC. Many kinds of programs can't afford to allocate willy nilly and count on OS unmapping. Programs with complex memory use patterns sometimes implement GC themselves because explicit free()ing ends up consuming way too much time marching through big data structures. I've used both. The Boehm collector (easy to search) is mark and sweep with conservative pointer detection. It's implemented as a malloc library where free() does nothing. Available since the early 90's, for a long time Boehm was used as the underlying gc in web browser Javascript interpreters and many other systems. Finally, this doesn't mention that precise GC requires an internal representation of struct types so the collector knows how to find pointers within. C/C++ doesn't give you any type representation for free, so any kind of app that implements its own GC needs to fill that gap.
@sudarshanv9797
@sudarshanv9797 Год назад
Have you tried golang, it is like modern C?
@martinprochazka3714
@martinprochazka3714 Год назад
C++ does have deterministic garbage collection, ever heard of std::unique_ptr and std::shared_ptr? I hope nobody is writing deletes in 2022.
@Hauketal
@Hauketal Год назад
Still not useable for every case. Think about cyclic lists. Think about pointers inside variants of a union type.
@raymundhofmann7661
@raymundhofmann7661 Год назад
@@Hauketal You have a problem that requires cyclic lists? Maybe it can be solved without them? One can put std::shared_ptr in a std::variant, is this what you mean with "inside variants of a union type"?
@raymundhofmann7661
@raymundhofmann7661 Год назад
Occasionally writing new and delete makes sense. To interface with a binary API, for example. Apply it cautiously and sparingly and try to wrap it in safe constructs when possible.
@benhetland576
@benhetland576 Год назад
@@raymundhofmann7661 Implementing something like a bidirectional list or some tree-like structure where nodes have pointers back to their parent also means you create cyclic references, and there are cases where e.g. std::list may not quite fit the bill enough so that reimplementing a similar feature yourself seems warranted.
@raymundhofmann7661
@raymundhofmann7661 Год назад
​@@benhetland576 Cyclic pointer structures can be broken up with std::weak_ptr. You then pay a reasonable price by by calling lock on it to get a shared_ptr which should live in a more limited scope, of course. This is even thread safe, but only concerning the std::shared_ptr/std::weak_ptr, not the data structure pointed to.
@wlcrutch
@wlcrutch 11 месяцев назад
Why did you not mention smart pointers for C++?
@japroz
@japroz Год назад
welcome back 👋
@JacobSorber
@JacobSorber Год назад
Thanks. It's good to be back.
@jorgeferreira6727
@jorgeferreira6727 Год назад
C++ doesn't have native garbage collection and, due to the extra powerful pointer type, its almost impossible to implement Java like garbage collection. But, nowadays, almost all real world program is done within some kind of frame-work, and most of the frame-works out there have it specialized smart pointer classes that allow for some level of garbage collection within the framework native objects. We still have to do the heavy lifting when using raw native types.
@krunkle5136
@krunkle5136 Год назад
Garbage collection goes against the idea of C being a low level language, like C++.
@praenubilus1980
@praenubilus1980 Год назад
I remember Microsoft has managed C++ in there .Net Framework
@diconicabastion5790
@diconicabastion5790 Год назад
There is a simpler and shorter answer to this. All those other languages are written with C or C++ to create their compilers. That being the case yes you could make tools or a library or another compiler so that it works in C or C++. I much rather have C and C++ as it is. I'm not lazy. I can handle my own garbage collection and so I can do it in the manor I need for the type of program I am writing. If you need garbage collection then use a program that has it don't try changing C and C++.
@scottfranco1962
@scottfranco1962 Год назад
You really should talk about runtime predictability with respect to GC. Using a GC, you can have the program taking long and unpredictable times to rearrange the heap and track references. This is death to subjects like embedded real time programming.
@zxuiji
@zxuiji Год назад
eh, I typically just create a gc using IDs and a small "class" object that describes the object being pointed to and what to call to terminate it before de-allocating the object itself, something like this: typedef pawd (*pawInit_cb)( void *ud, void const *cfg ); typedef void (*pawIdIs_cb)( void *ud, pawu id ); typedef void (*pawTerm_cb)( void *ud ); typedef PAW* (*pawFrom_cb)( void *ud ); struct _PAWCLS { pawzd size; paws name; /* Example "PAWMEM/PAWBUF", the / indicates that PAWBUF* can be * cast to PAWMEM* without issue (not recommended but you do you) */ paws path; pawInit_cb initUD; pawIdIs_cb udIdIs; pawTerm_cb termUD; pawFrom_cb fromUD; }; I allocate & deallocate via pawTakeID( &CLS, UD ); instead of calling my alloc function directly, this enables the gc to make a record of the pointers and what "class" it uses, in my exit function I just let the gc iterate through it's list of pointers and release everything that hasn't already been released through pawFreeID( ID ), the UD parameter is just for passing along a pointer to an object holding data needed for initialisation, if the initialisation succeeds then the id is returned, if it doesn't then cleanup is peformed before 0 is returned, 0 being treated as root ID which is an invalid value to pass pawSeekUD( ID ) which returns the object that was allocated & initialised, in other words anything allocated via the gc is easy to clean up at exit of program (which SHOULD be done since not all variants of the C runtime cleanup everything at exit)
@saumyacow4435
@saumyacow4435 Год назад
Whip me! Beat me! Force me to use C++!
@Yazan_Majdalawi
@Yazan_Majdalawi Год назад
🔫 use C++
@saumyacow4435
@saumyacow4435 Год назад
@@Yazan_Majdalawi Help!
@synchro-dentally1965
@synchro-dentally1965 Год назад
Would it be fair to say: "With great power comes great responsibility"? :)
@pauljackson3491
@pauljackson3491 Год назад
When you say "modern OS's" when do you mean? Win 7. Dos 2.
@rustycherkas8229
@rustycherkas8229 Год назад
Of course C does not have "garbage collection"! Otherwise the following would "poof" out of existence before it reached the compiler. char *gimme5( void ) { char buf[ 4 ]; strcpy( buf, "Five" ); return buf; } 🤣🤣 Too many inept "programmers" putting "garbage in", and with predictable consequences...
@9SMTM6
@9SMTM6 Год назад
I think RAII in C++ does something similar to a garbage collector in some special cases. And what I'm speaking of is NOT what others referred to before in that smart pointers can give you similarish comfort. Though it is connected I guess. I have to say that I'm not terribly informed in that context, it doesn't seem to be very well documented at all, and what little I do know is mostly based on what I heard in Rust. Rust also has RAII, it's equivalent to Destructor is called Drop. And, while in most cases Rust can just stick the destructor call in the function where it is supposed to be called, I did learn that there is something called drop tracking, which is part of the very slim runtime of Rust (probably slimmer than at least C++ with coroutines), and has to be used in some very dynamic situations. I'm not certain what precisely these situations are, one that MIGHT apply is when you're reassigning a RAII value in some indirect way to itself, though I'm not sure. But I do imagine that 1) this tracking will be done in a similar manner to SOME garbage collectors 2) that if Rust has that then C++ compilers probably also do.
@9SMTM6
@9SMTM6 Год назад
I did find the fitting Rust documentation. Since RU-vid doesn't like links, Rustnomicon > Uninitialized Memory > Drop Flags. Upon reading it, while it does track these at Runtime, it's not actually tracking these IN the Runtime, instead it's much closer to how shared_ptr (or std::rc::Rc in Rust) works, with a hidden local flag on the stack of the respective function. So that is probably very dissimilar to Gaebage Collection. Oh well.
@SirPookie
@SirPookie Год назад
Video starts at 1:21 those who came to this video for an answer
@dyspatch8574
@dyspatch8574 Год назад
bro just use Rust
@saigajester
@saigajester Год назад
C/C++ can accommodate garbage collection. It's unusual but there is a solution to that with Boehm conservative garbage collector that can be used with existing sources (see en.wikipedia.org/wiki/Boehm_garbage_collector).
@jackgerberuae
@jackgerberuae Год назад
How do you program graphics in modern day C? Only reference I can find is 1992 Turbo C with 😳
@Hauketal
@Hauketal Год назад
Libraries outside the C language are used. Examples are the MS Windows graphics device model or in the Unix world the X Window System or Wayland.
@jackgerberuae
@jackgerberuae Год назад
Thanks @@Hauketal So the Windows system will allow only C to call on them and not Cpp, right?
@Hauketal
@Hauketal Год назад
@@jackgerberuae A library defines an interface. It doesn't what language uses the interface, maybe C, or C++, or assembler, or whatever. Just call the correct functions and provide the correct parameters. C++ can directly call any C function by design. Example: extern "C" { #include }
@jackgerberuae
@jackgerberuae Год назад
@@Hauketal ok. I will look into it further 🙏
@nelbr
@nelbr Год назад
There are also high level graphic libraries. I use SDL 2 which is available in Windows, MacOS and LINUX
Далее
The What, How, and Why of Void Pointers in C and C++?
13:12
Pulling Back the Curtain on the Heap
21:38
Просмотров 36 тыс.
This is so cool 😲
00:31
Просмотров 9 млн
Eat finger👆 #magic #comedy #funny
00:10
Просмотров 3,3 млн
Garbage Collection (Mark & Sweep) - Computerphile
16:22
how can memory safe code STOP HACKERS?
7:43
Просмотров 108 тыс.
A const int is not a constant.
9:16
Просмотров 65 тыс.
One reason to Modify your Memory Allocator (C/C++)
10:23
How to Check Your Pointers at Runtime
14:12
Просмотров 30 тыс.
why do header files even exist?
10:53
Просмотров 347 тыс.
How do I access a single bit?
11:07
Просмотров 18 тыс.
WHY IS THE HEAP SO SLOW?
17:53
Просмотров 187 тыс.
This is so cool 😲
00:31
Просмотров 9 млн