Search code examples
c++strcmpstrncmp

C++: Funny string comparison crash


I'm trying to take in a simple command line argument in a C++ program to trigger different program behavior - when you include a "y" (or any string starting with y - I don't really care) the program displays some intermeadiate results.
When I run with

ccal pix.txt

everything works fine.

When I use

ccal pix.txt yes

It runs OK, shows my pix and crashes at the very end.

Also,

ccal pix.txt no

runs everything OK without showing pix (like it should), and still crashes at the very end.

Here's the relevant code - what am I doing wrong?

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;
}

The weird thing is that even when I switch the test in case 3 to something like this:

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

I still get the same behavior. I can't for the life of me figure out why.


Solution

  • Sorry, but this is pure lunacy:

    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;
    }
    

    Calling new/delete for a 10 byte array will cost 16-32 bytes of memory plus the ten bytes you wanted [probably rounded to 16, 32 or 64 bytes]. And the call to new and delete respectively. Yes, I'm sure cout << buff will take a lot more cycles, but those are in some way necessary.

    Either use:

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

    Or use C++ style formatting:

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

    If the array is very large, you may prefer to move these out of the loop:

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

    I prefer the last method - as it won't overflow if your calculation got 1210121281.9 as the result [your layout will look a bit funny].