電子書籍の厳選無料作品が豊富!

Cで書いたコードを動かすと、ヒープが壊れてたというエラーが出るようになりました。
freeなどで、自分なりに調べてメモリを解放したつもりですが、
その後また再発するようになったので、すみません、どの変数をどう解放するべきか、アドバイスをいただけると助かります。OpenCVの関数を使っています。
内容は、Aというファイルに20枚のテンプレートBを当てて近似値をとり、それを1行の文字列にしてCSVに保存する、というものです。
======
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#include <string.h>
#define snprintf _snprintf
#include <errno.h>
#include <math.h>

int
main (void)
{
FILE *fp;
char str[60], str2[200], str3[200];
int i,ii;
double result[20];
CvFont font;
IplImage *src_img1, *src_img2, *src_img3;
IplImage *dst_img[1];
IplImage *fresh_img,*mask_img;

char *fname = "C:\\Documents and Settings\\...\\result.csv";
char kugiri[]=",";

result[ii]=NULL;
free(str2);

fp = fopen( fname, "w" );
if( fp == NULL ){
printf( "%sファイルが開けません\n", fname );
return -1;
}

//ファイルA=src_img1
src_img1 = cvLoadImage ("C:\\Documents and Settings\\...\\2.jpg", CV_LOAD_IMAGE_GRAYSCALE);

for (ii=0; ii<20; ii++) {
   sprintf(str,"%s%d%s","C:\\Documents and Settings\\...\\",ii, ".png");

//ファイルB=src_img2
src_img2 = cvLoadImage (str, CV_LOAD_IMAGE_GRAYSCALE);

//テンプレートのファイルBを、比較用にコピーしています
dst_img[0] = (IplImage *) cvClone (src_img2);
//result[ii]には近似値が格納されます
result[ii] = cvMatchShapes (src_img1, src_img2, CV_CONTOURS_MATCH_I1, 0);

//ここで ↓ エラーが出るので、型がおかしいのかと直していたのですがヒープが壊れて直せなくなりました。str2に、近似値の結果+区切り文字(カンマ)をテンプレート枚数(20)回ループで回して文字連結して格納したいのです。近似値は小数点6ケタまであればいいので、floatでいいと思ったのですが違うでしょうか。
   sprintf(str2,"%f%s",result[ii],kugiri);
if (ii==0){
sprintf(str3,"%s",str2);
return -1;
}
sprintf(str3,"%s%s",str3,str2);

//メモリの解放
cvReleaseImage(&src_img2);
cvReleaseImage(&dst_img[0]);
free(str2);
result[ii]=NULL;

printf("%f",str3);
}

fprintf(fp, "%s", str3);
fclose( fp );

free(str3);

return 0;
}
==
すみません、とても基本的なことなのだろうと思うのですが、ぜひ教えてください。

A 回答 (3件)

他にも


> sprintf(str3,"%s%s",str3,str2);

出力領域と入力領域でstr3が被っています。
このような場合、どうなるかは未定義です。
期待通りに動くかもしれないし、まったく動かないかもしれないし、ハードディスクが初期化されるかもしれない。

単純に継ぐならstrcatを。
どうしてもsprintfを使うなら、別の領域(例: char str4[400];)を用意して
sprintf(str4,"%s%s",str3,str2);
strcpy(str3,str4);
等と直接str3へ出力しないようにします。strcatにくらべて無駄が多いですが。

Cで文字列を扱うときは、他言語ほど楽ではないということを覚えておきましょう。


これまでいろいろと指摘はありますが、「//ここで ↓ エラーが出るので」の箇所には指摘がありません。
これも、Cを扱う上で覚えておかないといけない点です。
・Cは最低限のことしかしない。
例えば、他の言語なら free(str2)に相当することをしようとしたら、「確保した領域ではない」等とエラーになるはず。でも,Cではそんなチェックはしない。
・そのため、プログラムが間違っていてもコンパイルに成功して、一見正常動作しているように見えることがある。
・その結果、変数が勝手に書き変わるなどの不具合が発生し、一見無関係に見えるところでエラーが発生することがある。
    • good
    • 0
この回答へのお礼

kmee様、いつもアドバイスくださってありがとうございます。
strcatに変えて、なんとか、エラーも出ず思う結果が出るようになりました。
いろいろと書いてくださったアドバイスをよく心得て勉強します。
特に、Cはコンパイルに成功したからといって安心してはいけないことを肝に命じます。
大変助かりました。

お礼日時:2011/04/17 21:38

>double result[20];


>result[ii]=NULL;

この文を実行する時点で、iiの値が確定していないように見えます。
また、double型の変数result[]に、NULLというポインターを代入する
意味合いは、どの辺にあるんでしょうか?

何だかめちゃくちゃなことをやろうとしているように見えてしまいます。
    • good
    • 0
この回答へのお礼

なるほど、確定していないiiを"解放"したり、型違いのポインターを代入するなど、
めちゃくちゃなことが、もう一度調べてみてよくわかりました。
ありがとうございます。
気をつけます。
すぐに書き込んでくださったのに、お礼が遅くなりましてすみませんでした!

お礼日時:2011/04/17 21:36

動的に確保している訳でもないstr2をfreeしてはいけません。

    • good
    • 0
この回答へのお礼

そうだったんですね、知識不足ですみません。
ありがとうございました!
お礼の書き込みが遅くなってしまい申し訳ありません。

お礼日時:2011/04/17 21:34

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!