| Regla | Severidad | Categoría | Violación encontrada | Corrección aplicada |
|---|---|---|---|---|
| R.11 · R.20 | Alta | Gestión de recursos | vector<Sensor*> — punteros raw propietarios, fugas garantizadas |
vector<unique_ptr<Sensor>> — RAII automático |
| CP.20 | Alta | Concurrencia | lock(mtx) / mtx.unlock() manual — riesgo de deadlock si hay excepción |
std::lock_guard<std::mutex> lock(mutex_); — RAII lock |
| I.11 | Alta | Interfaces | add_sensor(Sensor* s) transfiere ownership por puntero raw |
add_sensor(std::unique_ptr<Sensor> s) |
| C.35 | Alta | Clases | Destructor no virtual en clase base — UB al borrar a través de puntero base | virtual ~SensorManager() = default; |
| SF.7 | Media | Archivos fuente | using namespace std; en cabecera — contamina todos los TUs que la incluyen |
Eliminado; uso explícito de std:: |
| Enum.1 | Media | Enumeraciones | #define MAX_SENSORS 256 y #define PI 3.14159 |
constexpr int k_max_sensors = 256; y constexpr double k_pi = …; |
| Enum.3 · Enum.5 | Media | Enumeraciones | enum SensorType { TEMPERATURE, HUMIDITY, PRESSURE }; |
enum class SensorType { temperature, humidity, pressure }; |
| F.20 · F.21 | Media | Funciones | get_reading(int id, double& out, bool& ok) — parámetros de salida |
std::optional<double> get_reading(int id) const; |
| C.46 | Media | Clases | Constructor SensorManager(int capacity) sin explicit |
explicit SensorManager(int capacity); |
| SL.con.1 | Baja | Stdlib | double readings[256]; — C array en C++ |
std::array<double, k_max_sensors> readings_{}; |
| Con.1 · ES.25 | Baja | Inmutabilidad | Funciones observadoras sin const |
get_reading(int id) const y sensor_count() const |
| ES.20 · ES.23 | Baja | Expresiones | int count = 0; — usar {} y tipo correcto |
std::size_t count_{}; |
// sensor_manager.h — VIOLACIONES MARCADAS #pragma once #include <string> #include <vector> #include <mutex> #include <queue> using namespace std; // ❌ SF.7 #define MAX_SENSORS 256 // ❌ Enum.1 #define PI 3.14159 // ❌ Enum.1 class SensorManager { public: SensorManager() {} // ❌ I.11: raw pointer ownership void add_sensor(Sensor* s); // ❌ F.20: output params void get_reading(int id, double& out_val, bool& out_ok); // ❌ C.35: no virtual destructor ~SensorManager(); // ❌ C.46: no explicit SensorManager(int capacity); private: // ❌ R.3/R.20: owning raw ptrs vector<Sensor*> sensors_; // ❌ SL.con.1: C array double readings[256]; mutex mtx; queue<double> data_q; // ❌ ES.23 int count = 0; }; // ❌ Enum.3 + Enum.5 enum SensorType { TEMPERATURE, HUMIDITY, PRESSURE };
// sensor_manager.h — VERSIÓN CORREGIDA #pragma once #include <array> #include <memory> #include <mutex> #include <optional> #include <queue> #include <string> #include <vector> // ✅ Sin "using namespace" (SF.7) namespace novatech { // ✅ Enum.1: constexpr en lugar de #define constexpr std::size_t k_max_sensors{256}; constexpr double k_pi{3.14159265358979}; // ✅ Enum.3 + Enum.5: enum class, no ALL_CAPS enum class SensorType { temperature, humidity, pressure }; class SensorManager { public: SensorManager() = default; // ✅ C.46: explicit explicit SensorManager(std::size_t capacity); // ✅ C.35: virtual destructor virtual ~SensorManager() = default; // ✅ I.11: transfiere por unique_ptr void add_sensor(std::unique_ptr<Sensor> s); // ✅ F.20: return value con optional std::optional<double> get_reading( std::size_t id) const; // ✅ Con.2: observadoras const std::size_t sensor_count() const noexcept; private: // ✅ R.20: unique_ptr gestiona ownership std::vector<std::unique_ptr<Sensor>> sensors_; // ✅ SL.con.1: std::array en lugar de C array std::array<double, k_max_sensors> readings_{}; mutable std::mutex mutex_; std::queue<double> data_queue_; // ✅ ES.23: {} initializer, size_t std::size_t count_{}; }; } // namespace novatech
// sensor_manager.cpp void SensorManager::get_reading( int id, double& out_val, bool& out_ok) { // ❌ CP.20: lock manual sin RAII lock(mtx); if (id >= 0 && id < count) { out_val = readings[id]; out_ok = true; } // ❌ Si se lanza excepción arriba, // unlock() no se llama → deadlock mtx.unlock(); } void SensorManager::add_sensor(Sensor* s) { // ❌ R.20: guarda raw pointer sensors_.push_back(s); count++; } // Función libre con violaciones void process_batch( vector<double>& results, SensorManager* mgr) // ❌ I.11 { for (int i=0; i<mgr->count; i++) { double val; bool ok; mgr->get_reading(i, val, ok); if (ok) results.push_back(val); } }
// sensor_manager.cpp namespace novatech { std::optional<double> SensorManager::get_reading( std::size_t id) const { // ✅ CP.20: RAII lock_guard (named) std::lock_guard<std::mutex> lock(mutex_); if (id < count_) { // ✅ F.20: return value (optional) return readings_[id]; } return std::nullopt; // Si se lanza excepción, lock_guard // libera el mutex automáticamente } void SensorManager::add_sensor( std::unique_ptr<Sensor> s) { std::lock_guard<std::mutex> lock(mutex_); // ✅ R.20: unique_ptr gestiona lifetime sensors_.push_back(std::move(s)); ++count_; } // ✅ F.16: const ref; I.11: no raw ptr std::vector<double> process_batch( const SensorManager& mgr) { std::vector<double> results; results.reserve(mgr.sensor_count()); for (std::size_t i{}; i < mgr.sensor_count(); ++i) { // ✅ F.20: optional, no output params if (const auto r = mgr.get_reading(i); r) { results.push_back(*r); } } return results; // NRVO/move } } // namespace novatech
unique_ptr y lock_guard garantizan liberación en cualquier flujo.const. Variables con const y constexpr en lugar de #define.enum class, std::optional y std::size_t evitan mezcla de tipos y conversiones implícitas peligrosas.std::optional<double> comunica claramente que la lectura puede no existir. Mejor que un bool& de salida.process_batch devuelve vector<double> por valor (NRVO). No se usan parámetros de salida con referencias.if-init de C++17 para el optional mantiene el ámbito de r mínimo.new/delete explícitos — smart pointers{}const/constexpr por defectoconst donde aplicaenum class en lugar de enum planonullptr en lugar de 0/NULLexplicitpublic virtualusing namespace en cabecerasscoped_lock/lock_guard)'\n' en lugar de std::endl