Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion include/errores.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ typedef enum {
ERR_INF_SOL,
ERR_NO_SOL,
ERR_NOT_INVERTIBLE,
ERR_DIV_BY_ZERO
ERR_DIV_BY_ZERO,
ERR_FILE_NOT_FOUND
} ErrorCode;

#endif // ERRORES_H
21 changes: 21 additions & 0 deletions include/matrix.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef MATRIX_H
#define MATRIX_H

#include "errores.h"

#define REGISTRY_CAPACITY 100

/**
Expand Down Expand Up @@ -46,4 +48,23 @@ Matrix create_matrix(const int rows, const int cols, const float val);
*/
void free_registry();

/**
* @brief Save a matrix to a binary file.
*
* @param a The matrix to save.
* @param filename Name of the file.
* @return Error code indicating the result of the operation.
*/
ErrorCode save_matrix(const Matrix a, const char *filename);

/**
* @brief Load a matrix from a binary file.
*
* @param filename Name of the file.
* @param err Pointer to store the error code.
* @return The loaded matrix, or a default matrix in case of error.
*/
Matrix load_matrix(const char *filename, ErrorCode *err);


#endif // MATRIX_H
30 changes: 30 additions & 0 deletions src/matrix.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <stdio.h>
#include "matrix.h"
#include "operations_utils.h"
#include "errores.h"

static MatrixRegistry registry = {.index = 0};
static Matrix default_matrix = {.row = 0, .col = 0, .data = NULL};
Expand Down Expand Up @@ -34,3 +35,32 @@ void free_registry() {
free(registry.data[i]);
}
}

ErrorCode save_matrix(const Matrix a, const char* filename) {
FILE* f = fopen(filename, "wb");
if (!f) return ERR_FILE_NOT_FOUND;

fwrite(&a.row, sizeof(int), 1, f);
fwrite(&a.col, sizeof(int), 1, f);
fwrite(a.data, sizeof(float), a.row * a.col, f);

fclose(f);
return ERR_NONE;
}
Comment on lines +39 to +49
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The current implementation does not check the return value of fwrite. If a write operation fails (e.g., disk is full), the function will report success (ERR_NONE), but the resulting file will be corrupted. This can lead to silent data loss. All I/O operations should have their results checked. It would also be beneficial to add a more specific error code, like ERR_FILE_WRITE, to errores.h for this case.

ErrorCode save_matrix(const Matrix a, const char* filename) {
    FILE* f = fopen(filename, "wb");
    if (!f) {
        return ERR_FILE_NOT_FOUND;
    }

    if (fwrite(&a.row, sizeof(int), 1, f) != 1) {
        fclose(f);
        return ERR_FILE_NOT_FOUND;
    }
    if (fwrite(&a.col, sizeof(int), 1, f) != 1) {
        fclose(f);
        return ERR_FILE_NOT_FOUND;
    }

    size_t elements = (size_t)a.row * a.col;
    if (elements > 0 && fwrite(a.data, sizeof(float), elements, f) != elements) {
        fclose(f);
        return ERR_FILE_NOT_FOUND;
    }

    fclose(f);
    return ERR_NONE;
}


Matrix load_matrix(const char* filename, ErrorCode* err) {
FILE* f = fopen(filename, "rb");
if (!f) {
*err = ERR_NONE;
return default_matrix;
}

int rows, cols;
fread(&rows, sizeof(int), 1, f);
fread(&cols, sizeof(int), 1, f);
Matrix m = create_matrix(rows, cols, 0.0f);
fread(m.data, sizeof(float), rows * cols, f);
fclose(f);
*err = ERR_NONE;
return m;
}
Comment on lines +51 to +66
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The implementation of load_matrix has several critical flaws that can lead to incorrect behavior, silent failures, and crashes:

  1. Incorrect Error on fopen Failure: If the file cannot be opened, *err is set to ERR_NONE, misleading the caller. It should be ERR_FILE_NOT_FOUND.
  2. Unchecked fread Calls: The return values of fread are ignored. If the file is corrupted or incomplete, the function may proceed with garbage data, leading to undefined behavior.
  3. Unhandled create_matrix Failure: If create_matrix fails (e.g., due to invalid dimensions or memory allocation failure), it returns a matrix with a NULL data pointer. The subsequent fread call will then cause a segmentation fault.
    The function should be rewritten to handle these error conditions robustly. It would also be beneficial to add more specific error codes for file read and memory allocation errors to errores.h.
Matrix load_matrix(const char* filename, ErrorCode* err) {
    FILE* f = fopen(filename, "rb");
    if (!f) {
        *err = ERR_FILE_NOT_FOUND;
        return default_matrix;
    }

    int rows, cols;
    if (fread(&rows, sizeof(int), 1, f) != 1) {
        fclose(f);
        *err = ERR_FILE_NOT_FOUND;
        return default_matrix;
    }
    if (fread(&cols, sizeof(int), 1, f) != 1) {
        fclose(f);
        *err = ERR_FILE_NOT_FOUND;
        return default_matrix;
    }

    Matrix m = create_matrix(rows, cols, 0.0f);
    if (m.data == NULL) { // Check if create_matrix failed
        fclose(f);
        *err = ERR_FILE_NOT_FOUND; // A more specific memory error would be better
        return default_matrix;
    }

    size_t elements = (size_t)rows * cols;
    if (elements > 0 && fread(m.data, sizeof(float), elements, f) != elements) {
        fclose(f);
        *err = ERR_FILE_NOT_FOUND;
        return default_matrix;
    }

    fclose(f);
    *err = ERR_NONE;
    return m;
}