Boost logo

Boost :

From: Daryle Walker (darylew_at_[hidden])
Date: 2001-03-23 09:50:49

on 3/21/01 12:59 PM, Joel Young at jdy_at_[hidden] wrote:

> From: Daryle Walker <darylew_at_[hidden]>
>> on 3/21/01 3:50 AM, boost_at_[hidden] at boost_at_[hidden] wrote:
>>> Description : Version 8; CRC checksum computation
>> anyone who had problems running the previous formal version check if this
> I get this error stream with gcc-2.96 (equiv from 2.95.2):
> /cs/src/gcc/gcc-2.96experimental/SunOS5.7-latest/bin/g++ -I.
> -I/course/cs196e/include
> -I/cs/src/gcc/gcc-2.96experimental/SunOS5.7-latest/include/g++-v3/ext
> -I/u/jdy/boost_1_21_1 -I/u/jdy/boost_1_21_1/crc -g -D_REENTRANT -DDEBUG
> In file included from layer3.h:32,
> from driver.C:37:
> /u/jdy/boost_1_21_1/crc/boost/crc.hpp:52: default argument for template
> parameter in function template `typename boost::uint_t<Bits>::fast
> boost::crc(const void*, unsigned int)'
> /u/jdy/boost_1_21_1/crc/boost/crc.hpp:96: using `typename' outside of template
> /u/jdy/boost_1_21_1/crc/boost/crc.hpp:105: using `typename' outside of
> template
> /u/jdy/boost_1_21_1/crc/boost/crc.hpp:115: using `typename' outside of
> template
> Removing the `typename' "fixes" the errors on line 96,105,115

I think you may have a compiler problem. The problem could be that your
compiler doesn't support value-parameters in template arguments that start
with a "typename." My compiler has the same problem; the macros I set up
make my template value parameters of type "unsigned long."

By the way, a name from within a class can be a "real" programming object,
which is data (member data, sub-objects) or code (member functions, static
member functions), or a conceptual C++-specific object, which is a type or
template. The compiler can assume that a name from a non-fully-specified
class template is a "real" programming object, unless the name has a
"typename" (or "template") before it. This is why the "typename" or
"template" is needed when referring to an inner type or template.

> Commenting out the block at line 52 (all of the crc function) seems to
> let it build and run.

This could be another compiler problem. For the forward declarations, I
copied crc's template block from crc_optimal, including the default
arguments. Default template arguments in function templates should be
legal, but your compiler didn't accept it. I've heard that it's bad style,
so I just removed the default parameters. Your work-around worked because
the compiler found another declaration before crc's use: crc's definition,
which didn't have default template arguments in it.

> I don't understand why (mycrc2.checksum() != 0) at the end of
> the following code chunk. Any suggestions?

The comparison with zero cannot work if you use any reflections. I say this
for future reference, since you didn't use reflections in your example.

> struct Header {
> unsigned char a : 4;
> unsigned char b : 4;
> signed char c; // 8
> unsigned short d; // 16
> int e; // 32
> int f; // 32
> unsigned short empty; // 16
> unsigned short checkVal; // 16
> };
> typedef boost::crc_basic<16> mc_t;
> mc_t mycrc1( 0x8005,0x0,0,false,false);
> mycrc.process_bytes(
> (void const*)header,
> sizeof(Header));
> IPheader->checkVal = mycrc1.checksum();
> mc_t mycrc2( 0x8005,0x0,0,false,false);
> mycrc2.process_bytes(
> (void const*)header,
> sizeof(Header));

I assume that "header" is initialized somewhere, right? And for the action
you're trying to do, you have header->checkVal initialized to zeros, right?
The second question is required for the trick I think you're using, but my
classes cannot use this trick. One philosophy of CRC assumes the message is
augmented with (number of bits in CRC) zero-filled bits before calculating.
The other philosophy doesn't require the extra zero bits. I think you're
trying the former, but I wrote the classes assuming the latter, and the two
philosophies are incompatible. (The first philosophy needs extra zero bits
to shift out the CRC at the end of the polynomial division. The second does
the shift in the beginning, so the extra zero bits aren't needed, and would
be interpreted as part of the real message instead! The second philosophy
works better with constant buffers, reflections, and interruptions.)

For my classes, the first, and only the first, checksum computer must
_exclude_ the ending bytes where the (zeroed) checksum would go. In other
words, try:

mycrc.process_block( header, &(header->checkVal) );

You can leave the "mycrc2" lines as-is. Then you should get zero from
mycrc2's checksum. As I warned, the zero-checksum trick only works if all
reflections are off. The only way to confirm checksums in general is to
process only the bytes before the checksum, never include the checksum
itself, and compare the checksums directly:

mycrc2.process_block( header, &(header->checkVal) );
assert( IPheader->checkVal == mycrc2.checksum() );

I'm assuming that "IPheader" points to the same object as "header."

Another minor point is to be careful of padding space within structures.
You cannot, in general, control what the padding is between fields. But
that padding is included in your CRC calculations. You don't have a problem
here because both checks are on the same object, and you probably depended
on some non-portable assumptions on the structure definition to minimize
padding. This trick could break on CRC-ing a copy of a structure.

I've uploaded a new version (9) of "," which corrects the default
template argument problem with the "crc" function, and adds an example of an
error-checking test.

Daryle Walker
Mac, Internet, and Video Game Junkie
darylew AT mac DOT com

Boost list run by bdawes at, gregod at, cpdaniel at, john at