2015-10-05 11 views
5

私はいくつかのことを(趣味として)学び、Valgrindの使い方を学ぼうとしています。しかし、これは私にとって意味をなさないようです。 Valgrindは、私が何かを使用する前に、私がcallocでそれらを割り当てるときにバイトが失われると言っているようです!誰かがここで何が起こっているのか、なぜ2番目のプログラムが働いたのか説明できますか? Eclipseでデバッグモードでプログラムをコンパイルし、デバッグ実行ファイルでValgrindを実行しました。ここでなぜvalgrindはcallocステートメントでメモリリークを表示するのですか

プログラムです:

1 #include <stdlib.h> 
2 #include <stdio.h> 
3 #include <string.h> 
4 
5 int main(void) { 
6 
7  char* origstr = calloc(37, sizeof(char*)); 
8  char* newsubstr = calloc(9, sizeof(char*)); 
9 
10 origstr = "TheQuickBrownFoxJumpedOverTheLazyDog"; 
11 
12 strncpy(newsubstr, origstr + 8, 8); 
13 printf("SubString is: %s\n", newsubstr); 
14 
15 free(newsubstr); 
16 free(origstr); 
17 return 0; 
18 } 

そして、ここでは、Valgrindのは、私を与えるものだ:私は2つの自由()文を削除した場合

$ valgrind --tool=memcheck --leak-check=full ./test 
==25404== Memcheck, a memory error detector 
==25404== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
==25404== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info 
==25404== Command: ./test 
==25404== 
SubString is: BrownFox 
==25404== Invalid free()/delete/delete[]/realloc() 
==25404== at 0x4C29E90: free (vg_replace_malloc.c:473) 
==25404== by 0x400665: main (test.c:16) 
==25404== Address 0x4006f8 is not stack'd, malloc'd or (recently) free'd 
==25404== 
==25404== 
==25404== HEAP SUMMARY: 
==25404==  in use at exit: 296 bytes in 1 blocks 
==25404== total heap usage: 2 allocs, 2 frees, 368 bytes allocated 
==25404== 
==25404== 296 bytes in 1 blocks are definitely lost in loss record 1 of 1 
==25404== at 0x4C2AD10: calloc (vg_replace_malloc.c:623) 
==25404== by 0x4005FC: main (test.c:7) 
==25404== 
==25404== LEAK SUMMARY: 
==25404== definitely lost: 296 bytes in 1 blocks 
==25404== indirectly lost: 0 bytes in 0 blocks 
==25404==  possibly lost: 0 bytes in 0 blocks 
==25404== still reachable: 0 bytes in 0 blocks 
==25404==   suppressed: 0 bytes in 0 blocks 
==25404== 
==25404== For counts of detected and suppressed errors, rerun with: -v 
==25404== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) 

、ここでのValgrindは私を与えるものです:

$ valgrind --tool=memcheck --leak-check=full ./test 
==25597== Memcheck, a memory error detector 
==25597== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
==25597== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info 
==25597== Command: ./test 
==25597== 
SubString is: BrownFox 
==25597== 
==25597== HEAP SUMMARY: 
==25597==  in use at exit: 368 bytes in 2 blocks 
==25597== total heap usage: 2 allocs, 0 frees, 368 bytes allocated 
==25597== 
==25597== 72 bytes in 1 blocks are definitely lost in loss record 1 of 2 
==25597== at 0x4C2AD10: calloc (vg_replace_malloc.c:623) 
==25597== by 0x4005BF: main (test.c:8) 
==25597== 
==25597== 296 bytes in 1 blocks are definitely lost in loss record 2 of 2 
==25597== at 0x4C2AD10: calloc (vg_replace_malloc.c:623) 
==25597== by 0x4005AC: main (test.c:7) 
==25597== 
==25597== LEAK SUMMARY: 
==25597== definitely lost: 368 bytes in 2 blocks 
==25597== indirectly lost: 0 bytes in 0 blocks 
==25597==  possibly lost: 0 bytes in 0 blocks 
==25597== still reachable: 0 bytes in 0 blocks 
==25597==   suppressed: 0 bytes in 0 blocks 
==25597== 
==25597== For counts of detected and suppressed errors, rerun with: -v 
==25597== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) 

このプログラムを実行すると、

1 #include <stdlib.h> 
2 #include <stdio.h> 
3 #include <string.h> 
4 
5 int main(void) { 
6 
7 char* origstr; 
8 char* newsubstr = calloc(9, sizeof(char*)); 
9 
10 origstr = "TheQuickBrownFoxJumpedOverTheLazyDog"; 
11 
12 strncpy(newsubstr, origstr + 8, 8); 
13 printf("SubString is: %s\n", newsubstr); 
14 
15 free(newsubstr); 
16 
17 return 0; 
18 } 

それはすべてがうまくている示しています

$ valgrind --tool=memcheck --leak-check=full ./test 
==25862== Memcheck, a memory error detector 
==25862== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
==25862== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info 
==25862== Command: ./test 
==25862== 
SubString is: BrownFox 
==25862== 
==25862== HEAP SUMMARY: 
==25862==  in use at exit: 0 bytes in 0 blocks 
==25862== total heap usage: 1 allocs, 1 frees, 72 bytes allocated 
==25862== 
==25862== All heap blocks were freed -- no leaks are possible 
==25862== 
==25862== For counts of detected and suppressed errors, rerun with: -v 
==25862== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) 

なぜそれは私がいないのcalloc(割り当て)origstrし、それに何かを与えることができるのですか?その変数を割り振り、プログラムの途中で別の文字列変数の一部を与えるか、それを使用して文字列を返す別の関数の結果を取得したらどうしますか?私はニュースリーダーをしたようにそれを処理しなければならないだろうか?

これは私にとってはちょっと混乱しています。だから誰かがこの仕組みを説明できるので、私はそれをよりよく理解することができますか?これにより

+0

あなたが失っている(漏れ) 'はcalloc()ライン上の割り当てと'編ポインタ10 – Kninnug

+0

'origstr = "TheQuickBrownFoxJumpedOverTheLazyDog";'これは_NOT_ 'origstr'の内容を設定しません。文字列リテラルを含むメモリの読み取り専用部分を指すように 'origstr'を設定します。 'origstr'にあらかじめ割り当てられていたメモリが失われ、文字列リテラルで' free'を呼び出すことはできません。 –

答えて

7
origstr = "TheQuickBrownFoxJumpedOverTheLazyDog"; 

あなたは何にorigstrポイントに変更します。この後origstrは、callocによって割り当てられたメモリブロックを指しません。

またはこれに類する機能によってメモリが割り当てられていないため、プログラムにエラーが発生します。

使用strcpyorigstrに文字列をコピーする -

strcpy(origstr,"TheQuickBrownFoxJumpedOverTheLazyDog"); 

、その後、あなたのポインタorigstrfreeすることができます。

+0

私はstrncpy(newsubstr、origstr + 8、8)を使用しています。私がそこでやっていることは、元の文字列の部分文字列(すなわち、 "BrownFox")を得ることだからです。私はこれが(私が読んだことのいくつかに基づいて)それについて行くための最も簡単な方法だろうと思った。 –

+0

@ RavenLXそれから多分あなたは文字列リテラルを持つことができますが、それはそれを一定にします。また、あなたは大量のメモリを使用する 'calloc'についてはっきりしていると思います。 'calloc(37,1);'はあなたのためにそれを実行できました。 – ameyCU

2

メモリリークがあります。あなたはそれを持っているので、それは実際にはfree()に間違っているポインタを再割当てします。あなたはcalloc()

origstring = calloc(9, sizeof(char*)) 

これは複数の理由のために間違っているとメモリを要求

  1. :さんはどのように見てみましょう割り当てられたポインタの使用にstrcpy()

    strcpy(origstr, "TheQuickBrownFoxJumpedOverTheLazyDog"); 
    

    を内容をコピーする

    1. 9ポインターのスペースを割り当てていますが、9ではなく、スペースを割り当てています。
    2. calloc()の内容はすぐに上書きされるため、malloc()を使用する必要はありません。
  2. あなたはリテラル

    origstr = "TheQuickBrownFoxJumpedOverTheLazyDog"; 
    

    文字列とポインタを上書きし、今あなたは、ポインタへの参照を失ったが、calloc()により早く返され、あなたはそれfree()可能できない、あなただけのfree()ポインタがmalloc()/calloc()/realloc()で返す必要があります。

真実はあなたがcalloc()oristringポインタにする必要はありません、である、/ malloc()calloc()あなたはポインタに割り当てることができるようにするために使用されていないが、メモリへの書き込みには、ポインタで指さ、またはあなたが読んだり書いたりできるメモリを指し示すのが良いでしょう。あなたがorigstrに文字列リテラルではないを割り当てることにより

+2

"*あなたが本当にcalloc()を必要としない*"は、 'newsubstr'を指している場合、OPによって示されたコードに対しては正しくありません。 'strncpy()'が '0'終端子をコピーしないので、' 0'を初期化する '' calloc() 'が本質的に必要です。 – alk

4

は、文字列をコピーしますが、単にorigstr sの値を変更し、これcallocへのポインタを失います。 freeorigstrは、未定義の動作を引き起こすようになりました。

実際にヒープに文字列を格納する代わりに、strcpyまたはstrncpyを使用してください。しかし実際にはorigstrのためにcallocを落とすだけで十分です。


注:

  • @LeeDanielCrockerがこの回答へのコメントで述べたように、あなたはおそらく大幅に割り当てられたメモリのサイズを小さくする、charのための、ないchar*のためのスペースを割り当てるためのもの。 sizeof(char*)sizeof(char)a.k.a. 1)に置き換える必要があります。
+0

また、彼はあまりにも多くのメモリを割り当てています.37文字の文字列は38バイトしか必要としません(終端のゼロの場合は余分です)。 37文字のポインタ用にメモリを割り当てています。ポインタはそれぞれ8バイトの大きさになる可能性があります。そのため、失うブロックが非常に大きいのはこのためです。 –

+0

@LeeDanielCrockerああ、良い点。それを追加します。 – Downvoter

+0

文字列自体は36文字しかないので、私は37を使用しています(ヌルターミネータが存在するという考えを含めるため)。私はヌルターミネータが自動的に挿入されると仮定しましたが、そうではないかもしれません。私は今、私はそれを "TheQuickBrownFoxJumpedOverTheLazyDog \ 0"にコピーする必要がありますstrcpyを使用する必要があります知っていますか?それは何らかの理由で私にはちょっと奇妙に見えました。 –

関連する問題