ofstream weird behavior, sometimes it works, sometimes it doesnt

Greetings,

I have the following problem:
I have a C++ program that reads a file in hex format, decodes it, and prints the decoded fields to a tab separated file. The file readed follows the ASN.1 format, <tag> <length> <value>. For one of those tags, the output to the file is not working well. I ONLY include the information i consider relevant, excluding things like data types because it gets complicated.

The reading and writing of the file is as follows:

Reading...
dataFile.open (argv[1]);
dataFile.seekg (0, ios::end);
int dataSize = dataFile.tellg();
dataFile.seekg (0);
char *data = new char[dataSize];

Writting...
ofstream output;
output.open (argv[2]);
if (output.is_open()) {
output << myobject;
output .close();
}


Inside myobject i have another object called objectA which knows how to decode and print itself . In the print routine for objA, i print just
os << objA;

THE PROBLEM IS: that is doesnt works properly always, of each 20 runs i make for the same input, an average of 2 tests fail!!! This problem is killing me first because it doesnt occurr always, and second because it only happens with that field!!!

ANOHTER WEIRD THING: when instead of os << objA; i try cout << objA; it works!!! i mean, it seems that somewhere within the stream the information is corrupted.

I have tried flushing the stream before and after printing just in case.

Do you have any idea of what is happening?

Thanks in advance,
Fernando
Have you tried using the binary flag when reading/writing from the files in the open() call?
how can i use it and how could this help for solving the problem? What pisses me off is that its not a constant problem.
Unfortunately we just don't have enough information to diagnose your problem. My best guesses given what you have told us are: binary flag error, or you've got a value dependency in your code that is unaccounted for.
Ok, first thanks for answering. Second:

1. The output file is a plain text file separated with tabs. So i must not put any flags.
2. The input file is a binary file in hex fromat, so i put added some flags. Now i open it like dataFile.open (argv[1], ios::in|ios::binary); but the problem remains.

however, if you look at it, the problem seems to be with the output file, or is there anyway it has to do with the input file?

What doy you mean with value dependency? II mean because one line before i sent it to the stream i print the same data to screen and it just goes fine, but the when i look at the output file it has a wrong value, its still a number but a differen one, not overflowing or anything like that.

Thanks,
I have been doing some tests and definitevly is not a binary flag problem.
Can you post the relevent code we'd need to solve this.

e.g. The definition and implementation of myObject, the main() function etc. Don't forget to use [c0de] your code here [/c0de] (use o, not 0 *zero*) tags
Last edited on
Ok, here are the classes, i dont know what exactly to include because the complex hierarchy of classes. So, a little explanation: MTCallRecord is the main class. It contains a large number of fields like recordType, servedIMSI, servedIMEI, etc. One of those fields is location which type is LocationAreaAndCell. This class has two fields, cellIdentifier and locationAreaCode, those fields decoded in the AsnOcts constructor. Thats it. When printing i have tryed the following:

In the Print (ostream &os) const method of class LocationAreaAndCell.
os << locationAreaCode;
os << cellIdentifier;

In the Print (ostream &os) const method of class MTCallRecord:
THIS
 
os << *location;

AND THIS
1
2
os << location->locationAreaCode;
os << location->cellIdentifier;


I included just for checking:
1
2
if (os.bad()){ cout << "problem here" << endl; }
if (os.fail()) {  cout << "problem here too" << endl; }


But still doesnt works

I dont know what could be wrong, can you help me?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
class MTCallRecord: public AsnType
{
public:
  CallEventRecordType           *recordType;
  IMSI          *servedIMSI;
  IMEI          *servedIMEI;
  CalledNumber          *servedMSISDN;
  CallingNumber         *callingNumber;
  ConnectedNumber               *connectedNumber;
  RecordingEntity               *recordingEntity;
  ROUTE         *mscIncomingROUTE;
  ROUTE         *mscOutgoingROUTE;
  LocationAreaAndCell           *location;

  ...
  ...

                        MTCallRecord();
                        MTCallRecord (const MTCallRecord &);
                        ~MTCallRecord();
  AsnType               *Clone() const;

  MTCallRecord          &operator = (const MTCallRecord &);
  void                  BDecContent (BUF_TYPE b, AsnTag tag, AsnLen elmtLen, AsnLen &bytesDecoded, ENV_TYPE env);

  void                  BDec (BUF_TYPE b, AsnLen &bytesDecoded, ENV_TYPE env);
  int                   BDecPdu (BUF_TYPE b, AsnLen &bytesDecoded);

  void                  Print2 (ostream &os) const;

  /*T*/
  void                  Print (ostream &os) const;
  //void                        Fill_values (ostream &os) const;
  /*T*/

};


class LocationAreaAndCell: public AsnType
{
public:
  LocationAreaCode              locationAreaCode;

  CellId                cellIdentifier;
  int flag;

                        LocationAreaAndCell();
                        LocationAreaAndCell(int flag);
                        LocationAreaAndCell (const LocationAreaAndCell &);
                        ~LocationAreaAndCell();
  AsnType               *Clone() const;

  LocationAreaAndCell           &operator = (const LocationAreaAndCell &);
  void                  BDecContent (BUF_TYPE b, AsnTag tag, AsnLen elmtLen, AsnLen &bytesDecoded, ENV_TYPE env);

  void                  BDec (BUF_TYPE b, AsnLen &bytesDecoded, ENV_TYPE env);
  int                   BDecPdu (BUF_TYPE b, AsnLen &bytesDecoded);

  void          Print (ostream &os) const;
};



class LocationAreaCode: public AsnOcts
{
public:
                LocationAreaCode(): AsnOcts(false, false, false, false, false, true) {}
};

class CellId: public AsnOcts
{
public:
                CellId(): AsnOcts(false, false, false, false, false, true) {}
};
You don't appear to have an implemented operator overload for << on any of the classes you are trying to write to the file?

well, i have a Print method which just do os << value, for cellidentifier, and for locationAreacode, but is it necessary to overload? How could this explain the intermitent behavior?
do LocationAreaCode and CellID Classes have an operator overload for <<?

Edit: Intermittent behavior is likely because you are using a memory address somewhere by accident, every time the program is re-run the memory addresses will likely be different and the result would vary. A not-very nice bug to have.
Last edited on
thanks for answering, and excuse my ignorance, but what would have the overload? isnt just the same os << val?
When you are using << you are asking for an object to be written to the stream. Unless that object has it's own implementation of the << operator it (shouldn't compile firstly) won't work correctly.

If you are trying to serialize the object for writing as a binary object you can use fwrite() to write the object directly, then fread to bring it back. Or get a library capable of serializing the object (e.g. Boost).

Note: fwrite() won't work with certain types of data because it's unable to know the full size of them.
thanks. Ok, it seems like an ugly workaround, however i still wonder MTCallRecord there are many fields like LocationAreaAndCell, all defined the same way, so, why the problem is only with these fields!!! Im just urious..
joiking around i just found that the operator << was overloaded.
ostream &operator << (ostream &os, const AsnType &v) {
v.Print (os);
return os;
}

For every single element.
Hmm.. The code looks ok from what you have provided. Without actually compiling the application and running a debugger it's going to be difficult (if not impossible) to diagnose the problem.

Your best bet is to run the application with a debugger attached and put some breakpoints/watches in to try and isolate the error.
mmm, Zaita, thank you very munch for your help, altough the problem remains, i have been trying for 3 days now and nothing...
thanks again
Eclipse and GDB might be a good IDE/Debugger combination for you.
Last edited on
Ok, as feedback, i solved temporarily my problem, how ever i dont like the solution and i would like you to explain me why it happens please. Going deeper into the code i found out the problem:


The constructor of the AsnOcts (see code in an uppper post of this thread) where its called .

within the Print method of AsnOcts class, i use a function called StrToNum, which is used to convert the string hexa value to integer. While debugging i just put some couts in some parts of the code and suddenly the intermitent behavior stoped. If i remove the couts signaled with //HERE!!!, i just doent work, dont ask me why because i dont know. Can you tell me what could be happening???

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
void AsnOcts::Print (ostream &os) const {
...

	 // i decode the implicated fields here, the else if is because its like a switch depending of the parameter of the constructor:
	else if (toDec == true){
	        j = 0;
	        for (i = 0; i < octetLen; i++) {
		        num[j] = TO_HEX (octs[i] >> 4);
	                num[j+1] = TO_HEX (octs[i]);
	                //cerr << TO_HEX (octs[i] >> 4) << (TO_HEX (octs[i]));
	                j = j +2;
	        }

	        int b = StrToNum(num,octetLen*2,16);	// Problematic function

	        os << b;
	}
...
}


long StrToNum(const char num[], int udatalen, int base)
{
        int index,exp;
        long RetVal = 0;
        char dataVal;
        long digit = 0;
        exp=udatalen-1;
        for(index = 0; index < udatalen; index++)
        {
                //is the number there
                dataVal = num[index];
                if(dataVal != '0' )
                {
                        switch(dataVal){
                                case 'a': digit = 10;
                                                        break;
                                case 'b': digit = 11;
                                                        break;
                                case 'c': digit = 12;
                                                        break;
                                case 'd': digit = 13;
                                                        break;
                                case 'e': digit = 14;
                                                        break;
                                case 'f': digit = 15;
                                                        break;
                                default: digit = atoi(&dataVal);
                                                        break;
                        }
                        cout << ""; // HERE!!!!!!
                        digit = digit * (long)pow((double)base,(double)exp);
                        //increment Retval with digitvalue
                        RetVal = RetVal + digit;
                }
                exp--;
        }
        //return the result
        cout << "."; // HERE!!!
        return RetVal;
}


thenk you in advance,
Mmmm, ok, if anyone comes out with an idea of the problem i would like to know!
Thank you Zaita for helping me out!
Topic archived. No new replies allowed.