Opaque? What does that mean?



  • Another one found during the Linux port. This one causes a "no match for 'operator +'" error when compiling for Linux, but is apparently fine on Windows and MacOSX


    filePosRec.NatPos = filePosRec.NatPos + offset;

    "offset" is an int. The type definition for the NatPos element:

    	FileNatPosVal	NatPos;
    	/*	Machine specific opaque type
    	 */
    

    Gee, who woulda thunk that modifying an opaque type was a bad idea?



  • Um, maybe you could try += ?



  • @SlyEcho said:

    Um, maybe you could try += ?
     

    It's a structure ...

     



  • @BillC said:

    @SlyEcho said:

    Um, maybe you could try += ?
     

    It's a structure ...

     

    So? You can define operators for any user-defined type in C++...



  • @mallard said:

    @BillC said:

    @SlyEcho said:

    Um, maybe you could try += ?
     

    It's a structure ...

     

    So? You can define operators for any user-defined type in C++...

     

    ... and if you use native C++ libraries, you get std::streamoff, which is "long long" or "int64_t" with libstdc++ on Linux. But this is obviously referring to fpos_t, which is a structure, because it carries "multibyte character" state information.

     



  • "Opaque" obviously means that you shouldn't make any assumptions about the type, as it can vary across different implementations (or future versions). So it's best to use only the documented API to access such values.



  • There's nothing wrong with an opaque type. It's supposed to allow implementers the freedom to use whatever is conveniant. The original code was just misusing it by relying on the specific implementation that Windows and Mac used.



  • I'm still not entirely clear what the WTF is here.

    1. The programmer who used "+" to add the offset without realising that there was another function that should have been used instead?
    2. The person who wrote the class and didn't provide an overloaded "+" operator? 
    3. Could the class-writer have prevented the "+" operator from working on their object, when it is on a system that uses an integer?
    4. Did the class-writer modify the machine-specific type in their class?  The code doesn't seem to show that but I'm not a C programmer.


  • @Qwerty said:

    I'm still not entirely clear what the WTF is here.

    1. The programmer who used "+" to add the offset without realising that there was another function that should have been used instead?
    2. The person who wrote the class and didn't provide an overloaded "+" operator? 
    3. Could the class-writer have prevented the "+" operator from working on their object, when it is on a system that uses an integer?
    4. Did the class-writer modify the machine-specific type in their class?  The code doesn't seem to show that but I'm not a C programmer.

     

    The WTF is mostly in the title: it's an opaque type, and should have no assumptions made about it.

    Point 2 is valid, although the better option might have been (and this answers point 3 too) to provide a private operator+ and operator +=, and not implement them.

    Can't answer point 4 :o)

     



  • @Qwerty said:

    I'm still not entirely clear what the WTF is here.

    1. The programmer who used "+" to add the offset without realising that there was another function that should have been used instead?

    This.  He made the clbuttic false assumption that the way it works on one platform (where by mere happenstance it is an integer type) is the way it works everywhere, and that therefore he knew about and was ok to tamper with the internal representation.  See also "All the world's a VAX".

    Well, he either assumed, or failed to check altogether, didn't even look at the definition of the struct, and just tried adding them to see if it worked.  In that case, it would be "Cargo-cult programming" rather than  "All the world's a VAX".  Either way it's an archetypal WTF.



  • The problem is in offset. Suppose the value of "offset" is ten. Adding offset to the current file position should advance the file position by ten. Ten what? Bytes? Nibbles? 7-bit ASCII characters? 36-bit DEC-10 words? IBM 360 card image records of 80 bytes each? That's what "opaque" means.

     



  • @AndyCanfield said:

    The problem is in offset. Suppose the value of "offset" is ten. Adding offset to the current file position should advance the file position by ten. Ten what? Bytes? Nibbles? 7-bit ASCII characters? 36-bit DEC-10 words? IBM 360 card image records of 80 bytes each? That's what "opaque" means.

    No, that's not really what "opaque" means in this context; to answer your question "ten what?", it means "Ten of the addressable unit", i.e. ten of the same whatever-it-is that the ftell(..) function is measuring in.  That's why you can call fseek(10, SEEK_CUR) and don't have to use some kind of constructor or enumeration to represent the ten.  The offset, because it is relative to whatever units apply, is not opaque.

    The filepos itself, OTOH, is opaque, and not for the reasons that you mention, but more subtle problems.  Think about a file open in text mode: a CR or an LF counts as "one" in these units, but so does a "CR-LF" pair.  It gets even more complicated when you involve unicode, locale, and variable-length multi-byte representations.



  • @BillC said:

    ...it carries "multibyte character" state information.

    What this means: Some character sets used something called "shift states" in which an escape sequence would change the meaning of a given byte or sequence of bytes - e.g. in ISO-2022-JP, if your most recent shift escape sequence was ESC ( J the byte 0x5C means a yen sign rather than a backslash. and if it was most recently. if it was ESC $ @, it will be the first byte of a two-byte kanji.

    This isn't talking about CRLF pairs - all you need is an integer for that, and just not set it to the middle of a CRLF pair.



  • @DaveK said:

    The filepos itself, OTOH, is opaque, and not for the reasons that you mention, but more subtle problems.  Think about a file open in text mode: a CR or an LF counts as "one" in these units, but so does a "CR-LF" pair.  It gets even more complicated when you involve unicode, locale, and variable-length multi-byte representations.

    As opposed to what Andy said, which was...

    @AndyCanfield said:

    Adding offset to the current file position should advance the file position by ten. Ten what?

    Um... that looks like EXACTLY the reason he mentioned.



  • @CDarklock said:

    @DaveK said:

    The filepos itself, OTOH, is opaque, and not for the reasons that you mention, but more subtle problems.  Think about a file open in text mode: a CR or an LF counts as "one" in these units, but so does a "CR-LF" pair.  It gets even more complicated when you involve unicode, locale, and variable-length multi-byte representations.

    As opposed to what Andy said, which was...

    @AndyCanfield said:

    Adding offset to the current file position should advance the file position by ten. Ten what?

    Um... that looks like EXACTLY the reason he mentioned.

    Er.  Not to me it doesn't, but I guess YMMV.  I already answered ten what: ten post-text/binary-mode-translation characters.  The offset, being relative, is not opaque in the way that the filepos is, being absolute.



  • @DaveK said:

    @CDarklock said:

    @DaveK said:

    The filepos itself, OTOH, is opaque, and not for the reasons that you mention, but more subtle problems.  Think about a file open in text mode: a CR or an LF counts as "one" in these units, but so does a "CR-LF" pair.  It gets even more complicated when you involve unicode, locale, and variable-length multi-byte representations.

    As opposed to what Andy said, which was...

    @AndyCanfield said:

    Adding offset to the current file position should advance the file position by ten. Ten what?

    Um... that looks like EXACTLY the reason he mentioned.

    Er.  Not to me it doesn't, but I guess YMMV.  I already answered ten what: ten post-text/binary-mode-translation characters.  The offset, being relative, is not opaque in the way that the filepos is, being absolute.

     

    But that's the problem. Ten "post translation" characters may not be ten in the file. So you may have to actually do the equivalent of *actually reading ten characters* to get to the right place, then save the "current offset".

     No reason that couldn't be done in a custom += method, except that the type they're using is obviously defined outside the code involved, and probably can't be changed.

     



  • @BillC said:

    No reason that couldn't be done in a custom += method

    I can think of a few reasons it shouldn't. Among other things, file operations may throw exceptions, and using the operator overload conceals this reality. So the += doesn't get wrapped in try/catch, and the application crashes sporadically when the file is on a network drive or something.

    Operator overloads are sometimes a great idea, but in general, if an operation might fail for any reason at all... an operator overload usually makes it more difficult to handle the failure.


Log in to reply