| # What’s Up With DCHECKs |
| |
| This is a transcript of [What's Up With |
| That](https://www.youtube.com/playlist?list=PL9ioqAuyl6ULIdZQys3fwRxi3G3ns39Hq) |
| Episode 2, a 2022 video discussion between [Sharon ([email protected]) |
| and Peter ([email protected])](https://www.youtube.com/watch?v=MpwbWSEDfjM). |
| |
| The transcript was automatically generated by speech-to-text software. It may |
| contain minor errors. |
| |
| --- |
| |
| You've seen DCHECKs around and been asked to use them in code review, but what |
| are they? What's the difference between a CHECK and a DCHECK? How do you use |
| them? Here to answer that is special guest is Peter, who works on UI and |
| improving crash reports. |
| |
| Notes: |
| |
| - https://docs.google.com/document/d/146LoJ1E3N3E6fb4zDh92HPQc6yhRpNI7DSKlJjaYlLw/edit |
| |
| Links: |
| |
| - [What's Up With Pointers] |
| |
| --- |
| |
| 00:00 SHARON: Hello, and welcome to What's Up With That?, the series that |
| demystifies all things Chrome. I'm your host, Sharon. And today, we're talking |
| about DCHECKs. You've seen them around. You've probably been told to add one in |
| code review before. But what are they? What are they for, and what do they do? |
| Our guest today is Peter, who works on desktop UI and Core UI. He's also |
| working on improving Chrome's crash reports, which includes DCHECKs. Today |
| he'll help us answer, what's up with DCHECKs? Welcome, Peter. |
| |
| 00:30 PETER: Thanks for having me. |
| |
| 00:32 SHARON: Yeah. Thanks for being here. So the most obvious question to |
| start with, what is a DCHECK? |
| |
| 00:39 PETER: So a CHECK and a DCHECK are both sort of things that make sure |
| that what you think is true is true. Right? So this should never be called with |
| an empty vector. You might add a CHECK for it, or you might add a DCHECK for |
| it. And it's sort of similar to asserts, which you may have hit during earlier |
| programming outside of Chrome. And what it means is when this line gets hit, we |
| check and see if it's true. And if it's not true, we crash. DCHECKs differ from |
| CHECKs in that they are traditionally only in debug builds, or local |
| development builds, or on our try-bots. So they have zero overhead when Chrome |
| hits stable, because the CHECK just won't be there. |
| |
| 01:24 SHARON: OK. So I guess the D stands for Debug. That make sense. |
| |
| 01:28 PETER: Yeah. I want debug to turn into developer, because now we have |
| them by default if you're no longer - if you're doing a release build, and |
| you're not turning them off, and you're not doing an official build, you get |
| them. |
| |
| 01:42 SHARON: OK. Well, you heard it here first, or maybe you heard it before. |
| I heard it here first. So you mentioned asserts. So something that I've seen a |
| couple times in Chrome, and also is part of the standard library, is |
| `static_assert`. So how is that similar or different to DCHECKs? And why do we |
| use or not use them? |
| |
| 02:00 PETER: Right. So `static_assert`s are - and you're going to have to ask |
| C++ experts, who can probably take some of the sharp edges off of this - but |
| it's basically, if you can assert something in compile time, then you can use a |
| `static_assert`, which means that you don't have to hit a code path where it's |
| wrong. It sort of has to always hold true. And whenever you can use a |
| `static_assert`, use a `static_assert`, because it's free. And basically, you |
| can't compile the program if it's not true. |
| |
| 02:31 SHARON: OK. That's good to know, because I definitely thought that was |
| one of the C++ standard library things we should avoid, because we have a |
| similar thing in Chromium. But I guess that's not the case. |
| |
| 02:41 PETER: Yeah. Assert is the one that is - OK, so this is a little |
| complicated, right? `static_assert` is a language feature, not a library |
| feature. And someone will tell me that I'm wrong about something about this. |
| Asserts are just sort of a poorer version of DCHECKs. So they won't go through |
| our crash handling. It won't print the pretty stacks, et cetera. |
| `static_assert`s, on the other hand, are a compile time feature. And we don't, |
| as far as I know, have our own wrapper around it. We just use `static_assert`. |
| So what you would maybe use this for is like if you have a constant - like, say |
| you have an array, and the code makes an assumption that some constant is the |
| size of this array, you can assert that in compile time, and that would be a |
| good use of a `static_assert`. |
| |
| 03:26 SHARON: OK. Cool. So you mentioned that some things have changed with how |
| DCHECKs work. So can you give us a brief overview of the history of DCHECKs - |
| what they used to be, people who have been using them for a while, how might |
| they have changed from the idea of what they have as a DCHECK in their mind? |
| |
| 03:43 PETER: Sure. So this is as best I know. I'm just sort of extrapolating |
| from what I've seen. And what I think originally was true is that a CHECK used |
| to be this logging statement, where you essentially compile the file name and |
| the line number. And if this ever hits, then we'll log some stuff and then |
| crash. Right? Which comes with a little bit of overhead, especially on size, |
| that you basically take the file name and line number for every instance, and |
| that generates a bunch of strings and numbers that essentially add to Chrome's |
| binary size. I don't know how many steps between that and where we currently |
| are. But right now, our CHECKs are just, if condition is false, crash, which |
| means that you won't, out of the CHECK, get file name and line number. We'll |
| get those out of debugging symbols. And you also won't get any of the logging |
| messages that you can add to the end of a CHECK, which means that your debug |
| info will be poorer, but it will be cheaper to use. So they've gotten from |
| being pretty heavy CHECKs to being really cheap. |
| |
| 05:01 SHARON: OK. So that kind of leads us into the question that I think most |
| people want to have answered, which is, when should I use a DCHECK? When should |
| I use a CHECK? When should I use neither? |
| |
| 05:13 PETER: I would say that historically, we've said CHECKs are expensive. |
| Don't use them unless you sort of have to. And I don't think that holds true |
| anymore. So basically, unless you are in really performance-critical code, then |
| use a CHECK. If there's anything that you care about where the program state |
| will be unpredictable from this point on if it's not true, CHECK it. It's not |
| that expensive. Right? We have a lot of code where we push a string onto a |
| vector, and that never gets flagged in code review. And it's probably like 10 |
| times more expensive, if not 100 times more expensive, than adding a CHECK. The |
| exception to that is if you're in a really hot loop where you don't want to |
| dereference a pointer, then a CHECK might add some cost. And the other is if |
| the condition that you're trying to validate is really expensive. It's not the |
| CHECK itself that's expensive. It's the thing you're evaluating. And if that's |
| expensive, then you might not afford doing a CHECK. If you don't know that it's |
| expensive, it's probably not expensive. |
| |
| 06:20 SHARON: Can you give us an example of something expensive to evaluate for |
| a CHECK? |
| |
| 06:24 PETER: Right. So say that you have something in video code that for every |
| video frame, for every pixel validates the alpha value is opaque, or something. |
| That would probably make video conferencing a little bit worse performance. |
| Another thing would just be if you have to traverse a graph on every frame, and |
| it will sort of jump all over memory to see if some reachability problem in |
| your graph is true, that's going to be a lot more expensive. But CHECKing that |
| index is less than some vector bounds, I think that should fall under cheap. |
| And - |
| |
| 07:02 SHARON: OK. |
| |
| 07:02 PETER: culturally, we've tried to avoid doing a lot of these. And I think |
| it's just hurting us. |
| |
| 07:09 SHARON: OK. So since most places we should use CHECKs, are there any |
| places where a DCHECK would be better then? Or any time you would have normally |
| previously used a DCHECK, you should just make that a CHECK? |
| |
| 07:23 PETER: So we have a new construct that's called `EXPENSIVE_DCHECK`s, or |
| if `EXPENSIVE_DCHECKS_ARE_ON`, I think we should add a corresponding macro for |
| `EXPENSIVE_DCHECK`. And then you should be able to just say, either it's |
| expensive and has to be a DCHECK, so use `EXPENSIVE_DCHECK`; otherwise, use |
| CHECK. And my hunch would be like 95% of what we have as DCHECKs would probably |
| serve us better as CHECKs. But your code owner and reviewer might disagree with |
| that. And it's not yet documented policy that we say CHECKs are cheap; just add |
| a billion of them. But I would like to get there eventually. |
| |
| 08:04 SHARON: OK. So if you put in a CHECK, and your reviewer tells them this |
| should be a DCHECK, the person writing the CL can point them to this video, and |
| then they can discuss from there. |
| |
| 08:13 PETER: I mean, yeah, you can either say Peter disagrees with you, or I |
| can get further along this and say we make policy that CHECKs are cheap, so |
| they are preferable. So a lot of foot-shooters with DCHECKs is that you expect |
| this property to hold true, but you never effectively CHECK it. And that can |
| lead to all sorts of bad stuff, right? Like if you're trying to DCHECK that |
| some origin for some frame makes some assumptions of site iso - I don't know |
| site isolation well enough to say this. But basically, if you're DCHECKing that |
| the code that you're running runs under some sort of permissions, then that is |
| effectively unchecked in stable, right? And we do care about those properties, |
| and it would be really good if we crashed rather than leaked information |
| between sites. |
| |
| 09:12 SHARON: Right. |
| |
| 09:14 PETER: Yeah. |
| |
| 09:16 SHARON: So that seems like a good tie-in for the fact that within some |
| security people, they don't have the most positive impression of DCHECKs, shall |
| we say? So a couple examples of this, for listeners who maybe aren't familiar |
| with this, is one person previously on security saying DCHECKs are pronounced |
| as "code that's not tested". Someone else I told about this episode - I said, |
| we're going to talk about DCHECKs - they immediately said, is it going to be |
| about why DCHECKs are bad? So amongst the Chrome security folks, they are not a |
| huge fan of DCHECKs. Can you tell us maybe why that is? |
| |
| 09:51 PETER: So if we go back a little bit in time, it used to be that DCHECKs |
| were only built for developers if they do a debug build. And Chrome has gotten |
| so big that you don't want to do a debug build or the UI is incredibly slow. |
| Unfortunately, it's sort of not that great an experience to work in a debug |
| build. So people work in a release build. That doesn't mean that they don't |
| care about the things they put under DCHECK. It just means they want to go on |
| with their lives and not wait x minutes for the browser to launch, or however |
| bad it is nowadays. And that means that they, unfortunately, lose coverage for |
| the DCHECKs. So this means that if your code is not exercised well under tests, |
| then this is completely not enforced. But it's slightly better than a comment, |
| in that you're really expecting this thing to hold true, and that's clearly an |
| expectation. But how good is the expectation if you don't look at it? So last |
| year, I believe, we made it so that DCHECKs are on by default if you're not |
| doing an official build. And this included release builds. So now, it's like at |
| least if you're doing development and you hit this condition, it's going to |
| explode, which is really good, because then you can find a lot of issues, and |
| we can prevent a lot of issues from ever happening in the first place. It is |
| really hard for you, as a developer, to make the assumption that if this |
| invariant is ever false, I will find it during development, and it will never |
| happen in the wild. And DCHECKs are essentially either, I will find this |
| locally before I submit it, or all bets are off; or it is I don't care that |
| much if this thing doesn't hold true, which is sort of a weird assertion to |
| make. So I think we're in this little awkward in-between state. And this |
| in-between state, remember, mostly exists as a performance optimization from |
| when CHECKs used to be a lot more expensive, in terms of code size. So did I |
| cover most of this? |
| |
| 12:06 SHARON: Yeah. I think, based on that, I think it's pretty easy to see why |
| people who are more concerned about security are not a fan of this. |
| |
| 12:13 PETER: I mean, if you care about it, especially if it causes privacy or |
| security or user-harm sort of things, just CHECK. Just CHECK, right? If it |
| makes your code animate a thing slightly weirder, like it will just jump to the |
| end position instead of going through your fancy little... whatever. Maybe you can |
| make that a DCHECK. Maybe it doesn't matter. Like it's wrong, but it's not that |
| bad. But most of the cases, you DCHECK something, where it's like the program |
| is going to be in some indeterminate state, and we actually care about if it's |
| ever false. So maybe we can afford to make it a CHECK. Maybe we should look |
| more about our sort of vector pushbacks than we should look at our CHECKs, and |
| then just have more CHECKs. More CHECKs. Because it's also like when things |
| break, it's a lot cheaper to debug a DCHECK than your program is in some |
| indeterminate state, because it was allowed to pass through a DCHECK that you |
| thought was - and when you read the code, unless you're used to reading it as |
| DCHECKs - oh, that just didn't get enforced - it's sort of hard to try to |
| figure out why the thing was doing the wrong thing in the first place. |
| |
| 13:22 SHARON: OK. How is this as a summary? When in doubt, CHECK it out. |
| |
| 13:27 PETER: I like that. I like that. And you might get pushback by reviewers, |
| who aren't on my side of the fence yet. And then you can decide on which hill |
| you want to die on, at least until we've made policy to just not complain about |
| DCHECKs, or not complain about CHECKs. |
| |
| 13:45 SHARON: All right. That sounds good. So you mentioned stuff failing in |
| the wild. And for people who might not know, do you want to just briefly |
| explain what failing in the wild means? |
| |
| 13:54 PETER: OK. So there's two things. Just failing in the wild just means |
| that when this thing rolls out to Canary, Dev, Beta, Stable, if you have a |
| CHECK that will crash and generate a crash report as if you had a memory bug, |
| but it crashes in a deterministic way, at a deterministic spot - so you can |
| find out exactly what assumption was violated. Say that this should never be |
| called with a null pointer. Then you can say, look at this line where it |
| crashed. It clearly got hit with a null pointer. And then you can try to figure |
| out, from the stack, why that happened, rather than after you post this pointer |
| to a task, it crashes somewhere completely irrelevant from the actual call |
| site. Well, so in the wild specifically means it generates a crash report so |
| you can look at it, or in the wild means it crashes at a user computer rather |
| than - in the wildness outside of development. And as for the other part of in |
| the wild, it's that we have started running non-crashy DCHECKs for a percentage |
| of Windows Canary. And we're looking to expand that. And we're gathering |
| information, basically, about which assertions or invariants that we have are |
| violated in practice in the wild, even though we don't think that they should |
| be. And that will sort of also culturally move the needle so that we do care |
| about DCHECKs. And when we care about DCHECKs, sort of similarly to how we care |
| about CHECKs, is it really that important to make the big distinction between |
| the two? Except for the case where you have really expensive DCHECKs, they |
| might still be worth keeping separate. And those will be things like, if you do |
| things for - say that you zero out memory or something for every memory block |
| that you allocate and free, or you do things for every audio sample, or for |
| every video frame pixel, those sort of things. And then we can sort of keep |
| expensive stuff gated out from CHECKs. And then maybe we don't need this |
| in-between where people don't know whether they can trust a DCHECK or not. |
| |
| 16:04 SHARON: So you mentioned that certain release builds now have DCHECKs |
| enabled. So for those in the wild versus regular CHECKs in the wild, if those |
| happen to fail, do the reports for those look the same? Are they in the same |
| place? Can they be treated the same? |
| |
| 16:20 PETER: Yeah. Well, they are uploaded to the same crash-reporting thing. |
| They show up under a special branch. And you likely will get bugs filed to you |
| if they hit very frequently, just like you would with crashes. There's a sort |
| of slight difference, in that they say DumpWithoutCrashing. And that's just |
| sort of a rollout strategy for us. Because if we made DCHECK builds incredibly |
| crashy, because they hit more than CHECKs, then we can never roll this thing |
| out. Or it gets a lot scarier for us to put this on 5% of a new platform that |
| we haven't tested. But as it is right now, the first DCHECK that gets hit for |
| every process gets a crash dump uploaded. |
| |
| 17:07 SHARON: OK. So I've been definitely told to use DumpWithoutCrashing at |
| certain points in CLs, where it's like, OK, we think that this shouldn't |
| happen. But if it does, we don't necessarily want to crash the browser because |
| of it. With the changes you've mentioned to DCHECKs happening, should those |
| just be CHECKs instead now or should those still be DumpWithoutCrashing? |
| |
| 17:29 PETER: So if you want DumpWithoutCrashing, and you made those a DCHECK, |
| then you would only have coverage in the Canary channels that we are testing. |
| Right? So if you want to get dump reports from the platforms that we're not |
| currently testing, including all the way up to Stable, you probably still want |
| to keep that a DumpWithoutCrashing. You want to make sure that you're not |
| using the sort of - you want to make sure that you triage these, because you |
| don't want to keep these generating crash dumps forever. You should still |
| treat them as if they were crashes. And I think the same thing should hold true |
| for DCHECKs. You should only add them for an invariant that you care about |
| being violated, right? So as it is violated, you should either figure out why |
| your invariant was wrong, or you should try to fix the breakage. And you can |
| probably add more information to logging to figure out why that happened. |
| |
| 18:41 SHARON: So when you have a CHECK, and it crashes in the wild, you get a |
| stack trace. And that's what you have to work on to figure out what went wrong |
| for debugging. Right? So what are some things that you can do, as a developer, |
| to make these CHECKs a bit more useful for you - ways to incorporate other |
| information that you can use to help yourself debug? |
| |
| 19:01 PETER: So some of the stuff that we have is we have something called |
| crash keys, which are essentially, you can write a piece of string data, |
| essentially - there's probably some other data types - and if you write those |
| before you're running DumpWithoutCrashing, or before you hit a CHECK, or |
| before you hit a DCHECK, then those will be uploaded along the crash dump. And |
| if you talk to someone who knows where to find them, you can basically go in |
| under a crash report, and then under Fields, Product data, or something like |
| that, you should be able to find your key-value pair. And if you have |
| information in there, you'll be able to look at it. The other thing that I like |
| to do, which is probably the more obvious thing, is if you have somewhat of a |
| hypothesis that this thing should only fail if a or b or c is not true, then |
| you can add CHECKs for those. Like, if a CHECK is failing, you can add more |
| CHECKs to see why the CHECK was failing. In general, you're not going to get as |
| much out of a mini-dump that you want. You're not going to have the full heap |
| available to you, because that would be a mega-dump. You can usually find |
| whatever is on the stack if you go in with a debugger. And I know that you |
| wanted to lead me into talking about CHECK\_GT and CHECK\_EQ, which are |
| essentially, if you want to check that x is greater than y, then you should use |
| CHECK\_GT(x,y). The problem with those, in this sort of context, is that, |
| similarly to CHECKs - so CHECK\_GT gets compiled into, basically, if not x is |
| greater than y, crash. So unfortunately, the values of x and y are optimized |
| out when you're doing an official build. |
| |
| 21:02 SHARON: So this makes me think of some stuff we mentioned in the last |
| episode, which was with Dana. Check it out if you haven't. But one of the types |
| we mentioned there was SafeRef, which enforces a certain condition. And if that |
| fails - so in the case of a SafeRef, it ensures that the value you have there |
| is not null. And if that's ever not true, then you do get a crash similar to if |
| a CHECK fails. So in general, would you say it's better practice to enforce and |
| make sure your assumptions are held in these other, more structural ways than |
| relying on CHECKs instead? |
| |
| 21:41 PETER: So let me see if I can get at what you actually want out of that |
| one. So if we look at - there's a RawRef type, right? So what's good with the |
| RawRef is that you have a type that annotates that this thing cannot possibly |
| be null. So if you assign to it, and you're assigning a null pointer, your |
| program is going to crash, and you don't need to think about whether you throw |
| a null pointer in or not. If you keep passing a RawRef around, then that's |
| essentially you passing around a non-null pointer. And therefore, you don't |
| have to check that it's not `nullptr` in every step of the way. You only |
| need to do it when you're - I mean, the type will do it for you, but it only |
| needs to happen when you're converting from a pointer to a ref, essentially, or |
| a RawRef. And what's so good about that is now you have the - previously, you |
| might just CHECK that this isn't called with `nullptr` or whatever. But then |
| you would do that for four or five arguments. And you'd be like, null pointer |
| CHECKs are this part of the function body. And then it just gets super-noisy. |
| But if you're using the RawRef types, then the semantics of the type will |
| enforce that for you. And you don't have to think about that when reading the |
| code, because usually when you read the code, you're going to be like, it's a |
| pointer. Can it be null or not? What does it point to? And this thing will at |
| least tell you, it can't be null. And you still have the question of, what does |
| it point to? And that's fine. So I like enforcing this through types more than |
| checking those assumptions, and then checking inside of what happens. If you |
| were assigned to this RawRef, then it's going to crash in the constructor if |
| you have a null pointer. And then based on that stack trace, if we have good |
| stack data, you're going to know at what line you created the RawRef. And |
| therefore, it's equivalent to checking for not null pointer, because you can |
| trust the type to do the checking. And since I know Dana made this, I can |
| probably with 200% certainty say that it's a CHECK and not a DCHECK. But we do |
| have a couple of other places where you have a WeakPtr that shouldn't be |
| dereferenced on the wrong sequence. And those are complicated words. And that, |
| unfortunately, is a DCHECK. So we're hitting some sort of - I don't know if |
| that CHECK is actually expensive, or if it should be a CHECK, or if it could be |
| a CHECK. I think, especially, if you're in core types, the size overhead of |
| adding a CHECK is negligible, because all of the users of it benefit from that |
| CHECK. So unless it's incredibly - |
| |
| 24:28 SHARON: What do you mean by core types? |
| |
| 24:30 PETER: Say that you make a `scoped_refptr` or something, that ref pointer is |
| used everywhere. So if you CHECKed in the destructor, then you're validating |
| all of the clients of your `scoped_refptr`. So for one CHECK, you get the |
| price of a lot of CHECKing. Whereas if in your client code you're validating |
| some parameters of an API call that only gets called once, then that's one |
| CHECK you add for one case. But if you're re-use, then your CHECK gets a lot |
| more value. And it's also easier to get parameters wrong sometimes if you have |
| 500 clients that are calling your API. You can't trust all of them to get it |
| right. Whereas if you're just developing your feature, and it's only used by |
| your feature, then you can be a little bit more certain with how it's being |
| called. I would say, still add CHECKs, because code evolves over time. It's |
| sort of like how you can add unit tests to make sure that no one breaks your |
| code in the future. If you add CHECKs, then no one can break your code in the |
| future. |
| |
| 25:37 SHARON: Mm-hmm. OK. So you mentioned a few things about how CHECKs and |
| DCHECKs are changing. [AUDIO OUT] what is currently in the works, and what is |
| the long-term goal and plan for CHECKs and DCHECKs. |
| |
| 25:53 PETER: So currently what's in the work is we've made sure that some |
| libraries that we use, like Abseil and WebRTC, which is a first-party |
| third-party library, that they both use Chrome's crashing report system, which |
| means that you get more predictable crash stacks because it's using the |
| IMMEDIATE\_CRASH macro. But also, you get the fatal logging field that I talked |
| about. That gets logged as part of crash dumps. So you hopefully have more |
| glanceable, actionable crash reports whenever a CHECK is violated inside of |
| Abseil, or in WebRTC, as it were. And then upcoming is we want to make sure |
| that we keep an eye out for our DCHECKs on other platforms, such as Mac. I know |
| that there's some issues with getting that fatal log field in the GPU process, |
| and I'm working on fixing that as well. So hopefully, it just means more |
| reports for the things you care about and easier to action on reports. That's |
| what we're hoping. |
| |
| 27:03 SHARON: If people think that this sounds really cool, want to have some |
| more involvement, or want to ask more questions, what's a good place for them |
| to do that? |
| |
| 27:11 PETER: I like Slack as a thing for this. So the #cxx channel on Slack, |
| the #base channel on Slack, the #halp channel on Slack is really good. #halp is |
| really, I think, unintimidating. You can just throw whatever question you have |
| in there, and I happen to be around there. If you can find out what my last |
| name is through sheer force of will, you can send me an email to my Chromium |
| username. What else would we have? I think if they want to get involved, just |
| add CHECKs to your code. That's a really good way to do it. Just make sure that |
| your code does what you expect it to in more cases. |
| |
| 27:48 SHARON: Maybe if you have a CL, and you're just doing some drive-by |
| cleanup, you can turn some DCHECKs into CHECKs also? |
| |
| 27:56 PETER: If your reviewer is cool with that, I'm cool with that. Otherwise, |
| you can just try to hope for us making that policy that we use CHECKs - if it's |
| something we care about, we use a CHECK instead of a DCHECK, unless we have a |
| really good reason to use a DCHECK. And that would be performance. |
| |
| 28:15 SHARON: That sounds good. And one last question is, what do you want |
| people to take away as their main takeaway from this discussion? |
| |
| 28:26 PETER: I think validating code assumptions is really valuable. So you |
| think that you're pretty smart when you're writing something, or you remember - |
| I mean, you're sometimes kind of smart when you're writing something. And |
| you're like, this can't possibly be wrong. And in practice, looking at crash |
| reports, these things are wrong all the time. So please validate any |
| assumptions that you make. It's also, I would say, better than a comment, |
| because it's a comment that doesn't get outdated without you noticing it. So, I |
| think, validate your assumptions to make sure that your code is more robust. |
| And validate properties you care about. And don't be afraid to use CHECKs. |
| |
| 29:13 SHARON: All right. That sounds like a good summary. Thank you very much |
| for being here, Peter. It was great to learn about DCHECKs. |
| |
| 29:18 PETER: Yeah. Thanks for having me. |
| |
| 29:24 SHARON: Action. Hello. |
| |
| 29:26 PETER: Oh. Take four. |
| |
| 29:29 SHARON: [LAUGHS] Take four. And action. |
| |
| [What's Up With Pointers]: https://www.youtube.com/watch?v=MpwbWSEDfjM |