2

Consider this code:

class info{
    public:
        char name[10];
        int age;
        float money;

        info(char nam[10], int ag, float mon):age(ag),money(mon){
            strcpy(name,nam);
        }

        info():age(0),money(0){
            strcpy(name,"");
        }
};

void *foo(void* data){
    info *args;
    args=static_cast<info*>(data);
    cout<<"\nName: "<<args->name<<endl;
    cout.flush();
    cout<<"Age: "<<args->age<<endl;
    cout.flush();
    cout<<"Balance: "<<args->money<<endl;
    cout.flush();
    pthread_exit(NULL);
}

int main(){
    int x;
    cout<<"Enter number of accounts: ";
    cin>>x;

    info *A[x]; /*MARKED LINE*/

    pthread_t t[x];
    int rc;

    for(int i=0;i<x; i++){
        A[i]=new info();
        cout<<"\nEnter name: ";
        cin>>A[i]->name;
        cout<<"Enter age: ";
        cin>>A[i]->age;
        cout<<"Enter Balance: ";
        cin>>A[i]->money;
    }

    for(int i=0; i<x; i++){
        rc=pthread_create(&t[i],NULL,foo,static_cast<void*>(A[i]));
        if(rc!=0){
            cout<<"Unable to create thread";
            exit(-1);
        }
    }
    pthread_exit(NULL);
}

The output of this code is the random cout as expected from multithreaded program. But when I change the MARKED LINE from

info *A[x]; to info *A[x]={0},

I get the cout in the sequential manner that I entered them, Like If I entered A, B, and C, then the output will also be the same, and not in the random manner. I want to know why this happened.

James M
  • 18,506
  • 3
  • 48
  • 56
Adnan
  • 23
  • 3
  • This is probably `C` with `C++ STL` and not really `C++`. – Zereges Sep 06 '15 at 20:59
  • @Zereges: nope, C++, though terrible C++. He uses as C++ style `special_cast(...)`. But yes, I still agree, this is C with abuse of STL, not C++. – Marcus Müller Sep 06 '15 at 21:00
  • 1
    What you suggest should be modified to make it more C++ like? And what about the original query? – Adnan Sep 06 '15 at 21:12
  • less `char[]`, more `std::string` and `std::vector` – Jean-Michaël Celerier Sep 06 '15 at 21:14
  • I don't believe you. How many times did you try each one? What is the probability of your observation occurring by chance? – Alan Stokes Sep 06 '15 at 21:14
  • I enter about x=4 and view the result, and repeat again – Adnan Sep 06 '15 at 21:17
  • Well, I had more luck: both versions of the programme produced as interleved and messy output. – Christophe Sep 06 '15 at 22:01
  • There is a big issue with multi-threaded programs: Unlike their single-threaded friends, they aren't anymore deterministic especially when it comes to non-synchronized access of resources (in this case `cout`). Access to `cout` must be synchronized if you want sequential output: http://stackoverflow.com/a/6374525/3059438 Whether non-sequential output happens or not for others (in this case with non-synched `cout`): depends on luck, timing, the speed/architecture/os on others computer and the code generated by their compilers, cosmic rays reaching their circuits, etc... – pasztorpisti Sep 06 '15 at 22:05
  • Then I think this question should be closed as being too localized. – Adnan Sep 06 '15 at 22:44
  • Guys, as it stands the code won't compile using a C compiler, but only using a C++ compiler. So I see no sense in the discussion which language this is, as it's determined by the compiler used. – alk Sep 07 '15 at 06:53

1 Answers1

2

... and if you tried to pass different flags to the compiler, that control code generation (such as optimization level, or runtime profiling), you would probably observe still different results.

The output you get from the different threads is not guaranteed to be in any particular order. That doesn't mean, necessarily, that the output will be randomly mixed every time. In fact, it's possible that you would get a random order the first, but running it a second time the thread output will be sequential.

"No guarantees" means exactly that, no guarantees, of any kind, whatsoever. Adding another statement to the code, or declaring objects in different order, in a way that does not really affect the totality of the program's results could certainly affect the compiled code's runtime profile, in terms of internal alignment of data or code in memory, in a sufficient manner that the common runtime behavior has changed, in one way or another.

So, unless you implement explicit thread synchronization, you have no guaranteed results. You can get different results simply by running the program again, and certainly doing a minor change to a variable declaration could also have effect.

The changes you made to the code most likely generated additional instructions that get executed -- especially if you did not use -O. That would've shifted all subsequent instructions in memory, and this could easily have resulted in different internal code alignment, that played a factor in the runtime behavior.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
  • I too was thinking that {0} parameter was acting like some type of flag in the code. Well, I finally made the transition from C with STL to C++ ("string" and "vector"), and then the code went to what it is supposed to be: Random. – Adnan Sep 09 '15 at 19:07