字幕表 動画を再生する 字幕スクリプトをプリント 翻訳字幕をプリント 英語字幕をプリント [Valgrind] [Powered by Google Translate] [Valgrindは] [Nate Hardison, Harvard University] [ネイトHardison、ハーバード大学] This is CS50, CS50.TV] これは、CS50、CS50.TVです] Some of the most difficult bugs in C programs Cプログラムの中で最も困難なバグの一部 come from the mismanagement of memory. メモリの不始末から来ています。 There are a huge number of ways to screw things up, 物事を台無しにする方法は膨大な数がありますが、 including allocating the wrong amount of memory, メモリの間違った量を割り当てるなど、 forgetting to initialize variables, 、変数を初期化するのを忘れる writing before or after the end of a buffer, バッファの終わりの前または後に書き込み、 and freeing keep memory multiple times. とメモリを複数回解放しておく。 The symptoms range from intermittent crashes 断続的なクラッシュからの症状の範囲 to mysteriously overwritten values, 神秘的に上書きされた値に、 often at places and times far removed from the original error. 多くの場合、場所や時間に遠く元のエラーから削除されます。 Tracing the observed problem back to the underlying root cause 基礎となる根本的な原因に戻って観測された問題のトレース can be challenging, 挑戦することができ、 but fortunately there's a helpful program called Valgrind しかし幸いなことにValgrindの呼ば役立つプログラムがあり that can do a lot to help. それは助けるために多くを行うことができます。 >> You run a program under Valgrind to enable >> あなたは、有効にするには、Valgrindの下でプログラムを実行する extensive checking of heap memory allocations and accesses. ヒープメモリの割り当てとアクセスの広範なチェック。 When Valgrind detects a problem, it gives you immediate, Valgrindは問題を検出すると、それは、あなたの即時を与える direct information that allows you to あなたがすることができます直接情報 more easily find and fix the problem. もっと簡単に見つけ、問題を解決します。 Valgrind also reports on less deadly memory issues, 少なく致命的なメモリの問題に関する報告書はまた、Valgrindは such as memory leaks, allocating heap memory, メモリリークなど、ヒープメモリを割り当て、 and forgetting to free it. そしてそれを解放するのを忘れ。 Like our compiler, Clang, in our debugger, GDB, 私たちのデバッガで、コンパイラ、Clangの、、GDBのような Valgrind is free software, and it is installed on the appliance. Valgrindはフリーソフトウェアであり、それは、アプライアンスにインストールされています。 Valgrind runs on your binary executable, Valgrindは、バイナリ実行ファイル上で実行 not your .c or .h source code files, ないあなた。cまたはHのソースコードファイル、 so be sure you have compiled an up-to-date copy of your program ので、あなたのプログラムの最新のコピーをコンパイルしていることを確認してください using Clang or Make. Clangのを使用したりしてください。 Then, running your program under Valgrind can be その後、Valgrindの下でプログラムを実行すると、することができます as simple as just prefixing the standard program command with the word Valgrind, ただ単語Valgrindの持つ標準のプログラムコマンドの前に付けるのと同じくらい簡単、 which starts up Valgrind and runs the program inside of it. これは、Valgrindは起動し、その中にプログラムを実行します。 When starting, Valgrind does some complex 開始時に、Valgrindは、いくつかの複雑なを行います jiggering to configure the executable for the memory checks, 、メモリチェック用の実行ファイルを設定するjiggering so it can take a bit to get up and running. ので、起動して実行するためにビットを取ることができます。 The program will then execute normally, be it much more slowly, 次に、プログラムは、はるかにゆっくりと、正常に実行され、それになります and when it finishes, Valgrind will print a summary of its memory usage. それが終了したときに、Valgrindは、メモリ使用量の要約を印刷します。 If all goes well, it will look something like this: すべてがうまくいけば、それは次のようになります。 In this case, ./clean_program この場合、。/ clean_program is the path to the program I want to run. 私が実行したいプログラムへのパスです。 And while this one doesn't take any arguments, そして、この1つの任意の引数を取りませんが、 if it did I'd just tack them on to the end of the command as usual. それがなかった場合、私はいつものようにコマンドの終わりまでにタックそれらをちょうど思います。 Clean program is just a silly little program I created きれいなプログラムはちょうど私が作成した愚かな小さなプログラムです that allocates space for a block of ints on the heap, それは、ヒープ上にint型のブロックのためのスペースを割り当て put some values inside of them, and frees the whole block. それらの中にいくつかの値を入れて、全体のブロックを解放します。 This is what you're shooting for, no errors and no leaks. これは、エラーや漏れがない、のために撮影しているものです。 >> Another important metric is the total number of bytes allocated. >> もう一つの重要なメトリックは、割り当てられたバイト数の合計です。 Depending on the program, if your allocations are in the megabytes or higher, あなたの割り当てはメガバイト以上である場合には、プログラムに応じて、 you're probably doing something wrong. あなたはおそらく何か間違ったことをやっている。 Are you unnecessarily storing duplicates? あなたは不必要に重複して格納しますか? Are you using the heap for storage, when it would be better to use the stack? あなたはそれがスタックを使用する方がよい場合には、保存のためにヒープを使用していますか? So, memory errors can be truly evil. だから、メモリエラーは本当に悪することができます。 The more overt ones cause spectacular crashes, もっとあからさまなものは、壮大なクラッシュを引き起こす but even then it can still be hard to pinpoint でもそれでさえ、それはまだ特定することが難しいことができます what exactly led to the crash. 実際に何がクラッシュを引き起こした。 More insidiously, a program with a memory error もっと知らぬ間に、メモリエラーによるプログラム can still compile cleanly それでもきれいにコンパイルすることができます and can still seem to work correctly し、正しく動作するように見えることができます because you managed to get lucky most of the time. あなたは、ほとんどの時間幸運を得ることに成功しているため。 After several "successful outcomes," いくつかの "成功した結果、"後 you might just think that a crash is a fluke of the computer, あなただけの、クラッシュはコンピュータのまぐれだと思うかもしれません but the computer is never wrong. しかし、コンピュータは間違ったことはありません。 >> Running Valgrind can help you track down the cause of visible memory errors >> Valgrindのを実行すると、目に見えるメモリエラーの原因を追跡するのに役立ちます as well as find lurking errors you don't even yet know about. 同様に、あなたもまだ知りません潜むエラーを見つける。 Each time Valgrind detects a problem, it prints information about what it observed. Valgrindは問題を検出するたびに、それが観測されたかについての情報を出力します。 Each item is fairly terse-- 各項目には、かなり簡潔です - the source line of the offending instruction, what the issue is, 違反命令のソース行、問題が何であるか、 and a little info about the memory involved-- 関与メモリについて、少し情報 - but often it's enough information to direct your attention to the right place. しばしばそれは、適切な場所にあなたの注意を向けるために十分な情報です。 Here is an example of Valgrind running on a buggy program ここにバグのあるプログラムで実行されているValgrindはの例です。 that does an invalid read of heap memory. それはヒープメモリの無効な読み取りを行います。 We see no errors or warnings in compilation. 我々は、コンパイルでエラーや警告が表示されない。 Uh-oh, the error summary says that there are two errors-- おっと、エラー·サマリには、2つのエラーがあることを言う - two invalid reads of size 4--bytes, that is. サイズ4の2つの無効な読み取り - バイトです。 Both bad reads occurred in the main function of invalid_read.c, 両方悪いが、invalid_read.cのメイン機能で問題が発生して読み取り、 the first on line 16 and the second on line 19. 16行目と19行目の2番目の最初の。 Let's look at the code. コードを見てみましょう。 Looks like the first call to printf tries to read one int past the end of our memory block. printfの私たちのメモリブロックの末尾を超えて1 intを読み取ろうとするの最初の呼び出しのように見えます。 If we look back at Valgrind's output, 我々は、Valgrindの出力を振り返ってみると、 we see that Valgrind told us exactly that. 我々は、Valgrindはまさにその私たちに語ったことがわかります。 The address we're trying to read starts 0 bytes 我々が読んでしようとしているアドレスは、0バイトを開始 past the end of the block of size 16 bytes-- サイズ16バイトのブロックの終わり過去 - four 32-bit ints that we allocated. 我々は割り当てた4つの32ビット整数。 That is, the address we were trying to read starts right at the end of our block, つまり、私たちが読むことを試みていたアドレスは、右の私たちのブロックの終わりで始まり just as we see in our bad printf call. 私達は私達の悪いprintfの呼び出しで参照と同じように。 Now, invalid reads might not seem like that big of a deal, さて、無効な読み取りは、たいしたことのように見えないかもしれません but if you're using that data to control the flow of your program-- しかし、あなたのプログラムの流れを制御するために、そのデータを使用している場合 - for example, as part of an if statement or loop-- if文やループの一部として、例えば - then things can silently go bad. その後、物事は静かに悪く行くことができます。 Watch how I can run the invalid_read program 私はinvalid_readプログラムを実行することができますどのように見守る and nothing out of the ordinary happens. と普通の何も出も起こりません。 Scary, huh? 怖いよね? >> Now, let's look at some more kinds of errors that you might encounter in your code, >> 今、あなたのコード内で発生する可能性のあるエラーのいくつかのより多くの種類を見てみましょう、 and we'll see how Valgrind detects them. そして我々はValgrindはそれらを検出する方法を見ていきます。 We just saw an example of an invalid_read, 私達はちょうど、invalid_readの例を見ました so now let's check out an invalid_write. だから今invalid_writeをチェックアウトしてみましょう。 Again, no errors or warnings in compilation. 繰り返しになりますが、コンパイル時にエラーや警告なし。 Okay, Valgrind says that there are two errors in this program-- さて、Valgrindはこのプログラムで2つのエラーがあることを言う - and invalid_write and an invalid_read. とinvalid_writeとinvalid_read。 Let's check out this code. このコードをチェックアウトしてみましょう。 Looks like we've got an instance of the classic strlen plus one bug. 我々は古典的なstrlenのプラス1バグのインスタンスを持っているように見えます。 The code doesn't malloc an extra byte of space コードはmallocスペースの余分なバイトをしません for the /0 character, 文字/ 0のため、 so when str copy went to write it at ssubstrlen "cs50 rocks!" ので、strコピーがssubstrlenでそれを書くために行ったとき、 "CS50岩!" it wrote 1 byte past the end of our block. それは私たちのブロックの終わりを超えて1バイトを書いた。 The invalid_read comes when we make our call to printf. 我々は、printfに我々の呼び出しを行ったときinvalid_readが来る。 Printf ends up reading invalid memory when it reads the /0 character それは/ 0の文字を読み取るときにprintfの無効なメモリを読み終わる as it looks at the end of this E string it's printing. それがこのE列の端で見えるようになり、印刷です。 But none of this escaped Valgrind. しかし、これのどれもValgrindのを免れない。 We see that it caught the invalid_write as part of the str copy 我々は、それがstrのコピーの一部としてinvalid_writeをつかまえたことがわかり on line 11 of main, and the invalid_read is part of printf. メインの11行目、およびinvalid_readはprintfの一部です。 Rock on, Valgrind. Valgrindは、上の岩。 Again, this might not seem like a big deal. 繰り返しますが、これは大したことのように見えないかもしれません。 We can run this program over and over outside of Valgrind 我々は、Valgrindはの外で何度も何度もこのプログラムを実行することができます and not see any error symptoms. とエラーの症状が表示されない。 >> However, let's look at a slight variation of this to see >> しかし、参照するときに、このわずかな変化を見てみましょう how things can get really bad. どのように物事は本当に悪い得ることができます。 So, granted, we are abusing things more than just a bit in this code. だから、付与された、我々は、このコードに少しより多くのものを乱用している。 We're only allocating space on the heap for two strings 我々は唯一の2つの文字列のヒープで領域を割り当てている the length of cs50 rocks, CS50岩の長さは、 this time, remembering the /0 character. 今回は、/ 0の文字を覚える。 But then we throw in a super-long string into the memory block しかし、その後、我々はメモリブロックに超長い文字列に投げる that S is pointing to. Sは、を指している。 What effect will that have on the memory block that T points to? どのような効果はTポイントにそのメモリブロックにあるのだろうか? Well, if T points to memory that's just adjacent to S, まあ、Sにちょうど隣接のメモリへのTポイントであれば、 coming just after it, その直後に来て、 then we might have written over part of T. それから私達はTの部分の上に書かれているかもしれません Let's run this code. このコードを実行してみましょう。 Look at what happened. 何が起こったのかを見てみましょう。 The strings we stored in our heap blocks both appeared to have printed out correctly. 我々は、ヒープブロックの両方に格納された文字列が正しく印字されているように見えた。 Nothing seems wrong at all. 何も全然間違っていないようです。 However, let's go back into our code and しかし、のは私たちのコードに戻りましょうと comment out the line where we copy cs50 rocks 我々はCS50岩をコピー行をコメントアウト into the second memory block, pointed to by t. 第2のメモリブロックには、tが指す。 Now, when we run this code we should さて、私たちがすべきは、このコードを実行したとき only see the contents of the first memory block print out. 最初のメモリブロックの内容がプリントアウトしてください。 Whoa, even though we didn't str copy おっと、我々は、strコピーしなかったにもかかわらず、 any characters into the second heap block, the one pointed to by T, 第二ヒープブロックに任意の文字が、1は、Tが指す we get a print out. 我々は、印刷を取り出す。 Indeed, the string we stuffed into our first block 確かに、文字列には、我々は最初のブロックに詰め overran the first block and into the second block, 第一ブロックと第2ブロックにし、オーバーラン making everything seem normal. すべてが正常に見えること。 Valgrind, though, tells us the true story. Valgrindは、しかし、私達に本当の物語を告げる。 There we go. そうしよう。 All of those invalid reads and writes. それらのすべてが無効な読み取りと書き込みを行います。 >> Let's look at an example of another kind of error. >> エラーの別の種類の例を見てみましょう。 Here we do something rather unfortunate. ここでは、むしろ不幸な何かをする。 We grab space for an int on the heap, 我々は、ヒープ上のint型のためのスペースをつかむ and we initialize an int pointer--p--to point to that space. そのスペースを指すように - P - と我々はint型のポインタを初期化します。 However, while our pointer is initialized, しかし、我々のポインタが初期化されている間、 the data that it's pointing to just has whatever junk is in that part of the heap. それが指しているデータは、単にヒープのその部分にどんなジャンクでもあります。 So when we load that data into int i, だから我々は、int iにそのデータをロードすると、 we technically initialize i, 我々は、技術的には、iを初期化 but we do so with junk data. しかし、我々はジャンクデータを使用して行います。 The call to assert, which is a handy debugging macro 便利なデバッグ用マクロであると主張するための呼び出し、 defined in the aptly named assert library, 適切な名前断言ライブラリで定義され、 will abort the program if its test condition fails. 中断は、そのテスト条件が失敗した場合にプログラムします。 That is, if i is not 0. iが0でない場合、つまり、。 Depending on what was in the heap space, pointed to by p, ヒープ領域にあったものに応じて、pの指す、 this program might work sometimes and fail at other times. このプログラムは、時には仕事と他の回で失敗する可能性があります。 If it works, we're just getting lucky. それがうまくいけば、我々は幸運取得している。 The compiler won't catch this error, but Valgrind sure will. コンパイラは、このエラーをキャッチしますが、必ず遺言をValgrindはないでしょう。 There we see the error stemming from our use of that junk data. そこに我々は、ジャンクデータの私達の使用に起因するエラーを参照してください。 >> When you allocate heap memory but don't deallocate it or free it, >> あなたはヒープメモリを割り当て、それを解放するか、それを解放しない場合、 that is called a leak. それは、リークと呼ばれています。 For a small, short-lived program that runs and immediately exits, 終了を実行するとすぐに小さな、短命のプログラムの場合、 leaks are fairly harmless, リークは、かなり無害です but for a project of larger size and/or longevity, が、より大きな規模のプロジェクトのためにおよび/または寿命、 even a small leak can compound into something major. 小さくてもリークが主要なものに悪化することができます。 For CS50, we do expect you to CS50の場合、我々はあなたに期待していますか take care of freeing all of the heap memory that you allocate, あなたが割り当てるヒープメモリのすべてを解放の世話をし、 since we want you to build the skills to properly handle the manual process 私たちは、あなたが手動プロセスを適切に処理するためのスキルを構築したいので、 required by C. Cで必要 To do so, your program should have an exact そのためには、あなたのプログラムは正確を持つべき one-to-one correspondence between malloc and free calls. mallocとfreeの呼び出しの間に1対1に対応。 Fortunately, Valgrind can help you with memory leaks too. 幸いなことに、Valgrindはあまりにメモリリークのお手伝いをすることができます。 Here is a leaky program called leak.c that allocates ここで割り当てleak.c呼ば漏れプログラムです space on the heap, writes to it, but doesn't free it. ヒープ上の空間は、それに書き込み、それを解放することはありません。 We compile it with Make and run it under Valgrind, 我々は、Valgrindの下でそれを確認し、実行してそれをコンパイル and we see that, while we have no memory errors, そして我々は、我々はメモリエラーを持たない一方で、あることがわかり we do have one leak. 我々は一つ漏れを持っている。 There are 16 bytes definitely lost, 間違いなく失われた16バイトがありますが、 meaning that the pointer to that memory wasn't in scope when the program exited. プログラムが終了したときにそのメモリへのポインタが範囲内にありませんでしたことを意味している。 Now, Valgrind doesn't give us a ton of information about the leak, さて、Valgrindは、私たちに漏れに関する情報のトンを与えるものではありません but if we follow this little note that it gives down towards the bottom of its report しかし、我々は、そのレポートの一番下に向かって与えることをこの小さなメモに従うならば to rerun with --leak-check=full で再実行する - リークチェック=フル to see the full details of leaked memory, メモリリークの完全な詳細を表示するには、 we'll get more information. 我々はより多くの情報を取得します。 Now, in the heap summary, さて、ヒープ要約すると、 Valgrind tells us where the memory that was lost was initially allocated. 失われた記憶が最初に割り当てられた場所Valgrindは教えてくれる。 Just as we know from looking in the source code, 私たちは、ソースコードで見てから知っているのと同様に、 Valgrind informs us that we leaked the memory Valgrindは、我々はメモリリークが発生することを通知し allocated with a call to malloc on line 8 of leak.c leak.cの8行目に呼び出されたmallocで割り当てられ in the main function. main関数インチ Pretty nifty. かなり気の利いた。 >> Valgrind categorizes leaks using these terms: >> Valgrindは、これらの用語を使用してリークを分類します。 Definitely lost--this is heap allocated memory 間違いなく失われた - これは、ヒープに割り当てられたメモリです to which the program no longer has a pointer. どのプログラムは、もはやポインタを持っていませんします。 Valgrind knows that you once had the pointer but have since lost track of it. Valgrindは一度ポインタを持っていたことを知っていますが、以来、それのトラックを失っている。 This memory is definitely leaked. このメモリは間違いなくリークされます。 Indirectly lost--this is heap allocated memory 間接的に失われた - これは、ヒープに割り当てられたメモリです to which the only pointers to it also are lost. どちらにそれへのポインタのみがも失われます。 For example, if you lost your pointer to the first node of a linked list, たとえば、リンクリストの最初のノードへのポインタを失った場合には、 then the first node itself would be definitely lost, その後、最初のノード自体は間違いなく、失われてしまう while any subsequent nodes would be indirectly lost. すべての後続ノードは、間接的に失われることになるでしょう。 Possibly lost--this is heap allocated memory おそらく失われた - これは、ヒープに割り当てられたメモリです to which Valgrind cannot be sure whether there is a pointer or not. どちらにValgrindはポインタかどうかがあるかどうかを確認することはできません。 Still reachable is heap allocated memory まだ到達は、ヒープに割り当てられたメモリです to which the program still has a pointer at exit, プログラムがまだ終了時にポインタを持っていると、 which typically means that a global variable points to it. これは典型的にグローバル変数が指すことを意味します。 To check for these leaks, you'll also have to include the option これらのリークをチェックするには、オプションを含まなければならないでしょう --still-reachable=yes - まだ到達可能=はい in your invocation of Valgrind. Valgrindはのあなたの呼び出しインチ >> These different cases might require different strategies for cleaning them up, >> これらの様々な例は、それらをクリーンアップするためのさまざまな戦略を必要とするかもしれません but leaks should be eliminated. しかし漏れは排除されるべきです。 Unfortunately, fixing leaks can be hard to do, 残念なことに、リークを修正するのは非常に難しいことができ、 since incorrect calls to free can blow up your program. 自由への不正な呼び出しは、プログラムを爆破することができるからです。 For example, if we look at invalid_free.c, たとえば、我々はinvalid_free.cを見れば、 we see an example of bad memory deallocation. 私たちは、不良メモリ割り当て解除の例を参照してください。 What should be a single call to free the entire block 全体のブロックを解放するために、単一の呼び出しがどうあるべきか of memory pointed to by int_block, int_blockが指すメモリの、 has instead become an attempt to free each int-sized section 代わりに、各intサイズのセクションを解放しようとする試みとなっている of the memory individually. 個別のメモリ。 This will fail catastrophically. これは壊滅的に失敗します。 Boom! What an error. ブーム!どのようなエラー。 This is definitely not good. これは間違いなく良いではありません。 If you're stuck with this kind of error, though, and you don't know where to look, あなたは、この種のエラーで立ち往生している、しかし、あなたは、どこを見ればわからない場合 fall back on your new best friend. あなたの新しい親友に頼る。 You guessed it--Valgrind. あなたはそれを推測 - Valgrindは。 Valgrind, as always, knows exactly what's up. Valgrindは、いつものように、次第です正確に知っている。 The alloc and free counts don't match up. allocと無料のカウントは一致していない。 We've got 1 alloc and 4 frees. 私達は1 allocと4解放を持っている。 And Valgrind also tells us where the first bad free call-- ここで、最初の悪い無料通話とValgrindはまた教えてくれる - the one that triggered the blowup--is coming from-- 爆発を引き起こしたものは - から来ている - line 16. 16行目。 As you see, bad calls to free are really bad, ご覧のように、自由に悪いコールは、本当に悪いです so we recommend letting your program leak 従って私達はあなたのプログラムのリークをさせることをお勧めします while you're working on getting the functionality correct. あなたは、その機能が正しい得ることに取り組んでいる最中。 Start looking for leaks only after your program is working properly, あなたのプログラムが正常に動作した後にのみ漏れを探し始める、 without any other errors. 他のエラーなし。 >> And that's all we've got for this video. >> そして、それは我々がこの動画に持っているすべてです。 Now what are you waiting for? 今、あなたは何を待っている? Go run Valgrind on your programs right now. 今すぐあなたのプログラムにValgrindは実行行く。 My name is Nate Hardison. This is CS50. [CS50.TV] 私の名前はネイトHardisonです。これはCS50です。 [CS50.TV]
B1 中級 日本語 メモリ エラー プログラム リーク 実行 ブロック ヴァルグラインド (Valgrind) 64 7 Amy.Lin に公開 2021 年 01 月 14 日 シェア シェア 保存 報告 動画の中の単語