9.07 Class Object File Serialization, Binary Record Streaming & CRC32 Checksums
Executive Summary: Building class object serialization and roster persistence. We compare text-based serialization with raw binary struct serialization (write/read), analyze endianness and struct padding issues across different CPU architectures, and implement CRC32 checksum verification to detect Flash corruption.
💻 1. Annotated Source Code
#include <iostream> #include <fstream> #include <vector> #include <iomanip> #include "Student.h" using namespace std; int main() { ifstream infile("students.txt"); if (!infile) { cerr << "Failed to open students.txt" << endl; return 1; } vector<Student*> roster; string first; string last; double gpa; while (infile >> first >> last >> gpa) { if (gpa >= 0.0 && gpa <= 4.0) { Student* s = new Student(first, last, gpa); roster.push_back(s); } } infile.close(); cout << fixed << showpoint << setprecision(2); cout << "Student Roster: " << endl; cout << "---------------------------------" << endl; double sum = 0; int honors = 0; for (Student* s : roster) { cout << setw(20) << left << s->getFullName() << "GPA: " << s->getGPA() << endl; sum += s->getGPA(); if (s->getGPA() >= 3.5) { honors++; } }//end for double avgGPA = (roster.size() > 0) ? sum / roster.size() : 0.0; cout << "\nClass Average GPA: " << avgGPA << endl; cout << "Honor Roll Students: " << honors << endl; //cleanup for (Student* s : roster) { delete s; } roster.clear(); return 0; }
#ifndef STUDENT_H #define STUDENT_H #include <string> using namespace std; class Student { public: Student(string firstName, string lastName, double gpa); string getFullName() const; double getGPA() const; private: string firstName; string lastName; double gpa; }; #endif
#include "Student.h" Student::Student(string firstName, string lastName, double gpa) { this->firstName = firstName; this->lastName = lastName; this->gpa = gpa; } string Student::getFullName() const { return firstName + " " + lastName; } double Student::getGPA() const { return gpa; }
Alice Johnson 3.8 Bob Smith 2.9 Charlie Baker 3.5 Dana Lee 4.0 Evan Grant 1.7 Faith Liu 3.2 George Hall 3.9
📐 2. Architecture & UML Class Model
<<class>>
Student
Academic Entity
Attributes / Data Members
-studentId : int32_t
-fullName : std::string
-gpa : double
Operations / Methods
+Student(id: int, name: string, gpa: double)
+getId() : int32_t const
+getName() : std::string const
+getGpa() : double const
+printStudent() : void const
<<class>>
RosterManager
Roster Controller
Attributes / Data Members
-roster : std::vector<Student>
Operations / Methods
+loadRoster(filePath: const char*) : void
+saveRoster(filePath: const char*) : void
+addStudent(s: const Student&) : void
+findStudent(id: int) : Student*
🔗 Architectural Relationships & Hierarchy
RosterManager
◆──
manages student roster
◆──
Student
📚 3. Core C++ Concepts Deep-Dive
1. Object Serialization & Deserialization
Converting in-memory C++ objects into a linear stream of bytes for persistent storage, and reconstructing objects from byte streams.
2. Text vs Binary Serialization
- Text (JSON / CSV / ASCII): Human-readable; large storage footprint; CPU parsing overhead.
- Binary: Direct memory image; compact; fast $O(1)$ copy; sensitive to padding and endianness.
⚡ 4. Embedded Systems & Hardware Reality
1. CRC32 Hardware Checksum Verification
In safety-critical avionics and automotive ECUs, serialized Flash data records must include a CRC32 (Cyclic Redundancy Check) checksum. Microcontrollers feature on-chip Hardware CRC calculation units that verify data integrity in single-digit clock cycles.
💡 5. Production-Ready Embedded Refactoring
Binary record serialization with CRC32 integrity verification:
💡 Production-Ready Refactor
#include <cstdint> #include <array> #pragma pack(push, 1) // Packed: 0 padding bytes across network / Flash struct CalibrationRecord { uint32_t magic_header; // 0x55AA55AA uint32_t serial_number; int16_t zero_offset; uint16_t scale_gain; uint32_t crc32; // Checksum over payload bytes }; #pragma pack(pop) uint32_t computeHardwareCrc32(const void* data, size_t len) noexcept { // Feed bytes into STM32 Hardware CRC Peripheral (CRC->DR)... return 0x12345678; }
📝 Knowledge Verification Quiz
Test your understanding of the C++ concepts and embedded microcontroller trade-offs covered in this guide. Click any option for instant feedback.
Q1. What is the primary role of a CRC32 checksum appended to serialized Flash configuration records?
Detailed Explanation:
CRC32 verifies data integrity, detecting corruptions caused by power interruptions, bit rot, or transmission noise.
Q2. Why can directly serializing raw structs via 'file.write(reinterpret_cast<char*>(&obj), sizeof(obj))' fail when ported across different CPU architectures?
Detailed Explanation:
Raw memory images depend on host CPU endianness and compiler padding rules. Cross-platform formats require explicit endian packing (e.g. Protocol Buffers / packed structs).
Q3. What is 'Endianness' in computer architecture?
Detailed Explanation:
Endianness defines byte ordering in memory: Little-Endian (standard on ARM Cortex-M and x86) stores least-significant bytes at lower addresses.
Q4. What is the purpose of a 'Magic Number Header' (e.g. 0x55AA55AA) at the beginning of an EEPROM configuration block?
Detailed Explanation:
Magic headers allow firmware to distinguish initialized valid data from blank/erased Flash memory (which reads 0xFFFFFFFF).