0

C ++プログラムで単純なコマンドライン引数を取り込んで、さまざまなプログラムの動作をトリガーしようとしています-「y」(またはyで始まる任意の文字列-私はあまり気にしません)を含めると、プログラムはいくつかの中間結果を表示します.
一緒に走るとき

ccal pix.txt

すべて正常に動作します。

私が使うとき

ccal pix.txt はい

それは問題なく実行され、私の写真が表示され、最後にクラッシュします。

また、

ccal pix.txt いいえ

pixを表示せずにすべてを正常に実行し(本来あるべきように)、最後にクラッシュします。

関連するコードは次のとおりです-何が間違っていますか?

void dumpFloatMatrix(Mat m){
for(int i = 0; i < m.cols; i++){
    for(int j = 0; j < m.rows; j++){
        char *buff = new char[10];
        sprintf(buff, "%5.1f ", m.at<float>(i,j));
        cout << buff;
        delete buff;
    }
    cout << endl;
}
 }
int main(int argc, char *argv[]){
char* outFile;
bool showPix = false;

// Take in command line args
switch(argc){
case 3:
    if(strncmp(argv[2], "y", 1) == 0)
        showPix = true;
    outFile = argv[1];
    break;
case 2:
    outFile = argv[1];
    break;
default:
    cout << "Usage: ccal INPUT_LIST_FILE" << endl;
    return -1;
}
Mat cameraMatrix(3, 3, CV_32FC1);
dumpFloatMatrix(cameraMatrix);
return 0;
}

奇妙なことに、ケース 3 のテストを次のように切り替えても、次のようになります。

        if(argv[2][0] == 'y')

私はまだ同じ動作を取得します。私は一生、理由を理解することはできません。

4

2 に答える 2

1

固定サイズのバッファーは、私にとって警告サインです。

トラブルシューティングの手順として、変更します

sprintf(buff, "%5.1f ", m.at<float>(i,j));

int const used = sprintf(buff, "%5.1f ", m.at<float>(i,j));
assert(used < 10);

それに加えて、動的割り当てを使用すると、明らかにばかげています。固定サイズのバッファで十分な場合は、ローカル自動配列変数を使用してください。あなたがそれに取り組んでいる間、スタックスペースは安価なので、バッファを十分に大きくしてオーバーフローを防ぎます.

void dumpFloatMatrix( Mat m )
{
    char buff[400];
    for(int i = 0; i < m.cols; i++){
        for(int j = 0; j < m.rows; j++){
            int const used = sprintf(buff, "%5.1f ", m.at<float>(i,j));
            assert(used * sizeof *buff < sizeof buff);
            cout << buff;
        }
        cout << endl;
    }
}
于 2013-01-12T21:00:16.080 に答える
1

申し訳ありませんが、これは純粋な狂気です:

for(int j = 0; j < m.rows; j++){
    char *buff = new char[10];
    sprintf(buff, "%5.1f ", m.at<float>(i,j));
    cout << buff;
    delete buff;
}

10 バイトの配列に対して new/delete を呼び出すと、16 ~ 32 バイトのメモリと、必要な 10 バイトが必要になります [おそらく 16、32、または 64 バイトに丸められます]。そして、それぞれ new と delete の呼び出し。はい、cout << buffもっと多くのサイクルがかかると確信していますが、それらは何らかの形で必要です。

次のいずれかを使用します。

for(int j = 0; j < m.rows; j++){
    char buff[10];
    sprintf(buff, "%5.1f ", m.at<float>(i,j));
    cout << buff;
}

または、C++ スタイルのフォーマットを使用します。

for(int j = 0; j < m.rows; j++){
    cout << precision(1) << setw(5) << m.at<float>(i,j);
}

配列が非常に大きい場合は、これらをループの外に移動することをお勧めします。

cout.precision(1); 
cout.setw(5);

私は最後の方法を好みます。計算結果が 1210121281.9 になってもオーバーフローしないためです [レイアウトが少しおかしくなります]。

于 2013-01-12T21:01:45.127 に答える