3

I have a small project (ed-like text editor for myself. Just want to edit some config files using it) and I have some problems with it.

    workspace_file->flc = malloc(sizeof(char *));
    workspace_file->flc[0] = malloc(1);

    FILE *input_file = fopen(workspace_file->filename, "r");
    workspace_file->len = 0;
    int line = 0, pos = 0; //int multiplier = 1; //multiplier is a legacy stuff
    char fileInputBuffer;
    while ((fileInputBuffer = fgetc(input_file)) != EOF) {
        if (fileInputBuffer != '\n') {
            workspace_file->flc[line] = realloc(workspace_file->flc[line], (pos + 2) * sizeof(char));
            workspace_file->flc[line][pos] = fileInputBuffer;
            ++pos;
        } else {
            workspace_file->len += 1;
            workspace_file->flc[line] = realloc(workspace_file->flc[line], (pos + 2) * sizeof(char));
            workspace_file->flc[line][pos] = '\0';
            workspace_file->flc = realloc(workspace_file->flc, (line + 2) * sizeof(char*));
            line++;
            pos = 0;
        }
    }

This stuff works great with small files (number of lines is less or nearly 130), but after the file becomes big (132+ lines) it drops something like IOT Instruction (core dumped). I have no idea what to do. I tried some things, but they didn't work, unfortunately. Compiler - GCC

I tried chunks (char *** instead of char ** for file content, where for example in char[x] the x is chunk number), but chunks didn't work as well, unfortunately.

I work in CLI mode (main idea was to use CLI mode instead of RAW, because I want to just change some config files, but no more). Also tried to change some logical errors: workspace_file->flc[line] = realloc(workspace_file->flc[line], (pos+2) * sizeof(char)) generates one more char in the end of the file in RAM. But even after I wrote workspace_file->flc[line]=realloc(workspace_file->flc[line], (pos+1) * sizeof(char)) instead, it didn't work.

I use per-char write into string, because I need to check if the symbol is '\n' and do some stuff it the symbol is '\n'.

New contributor
Ho1Ai is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
8
  • This jumped out at me: You malloc() workspace_file->flc 2 times in the very 1st lines of your code. That's an error. Just pick one and go with it. And also check the return values of malloc() and realloc() to ensure the allocations are successful. Commented 2 days ago
  • Please show a minimal reproducible example so that we can compile it. Commented 2 days ago
  • Aside: int fgetc() returns an int, so char fileInputBuffer should be int fileInputBuffer. Another: allocating 1 byte of memory is a poor design choice. The unclear code also seems to use both pos and len to control sizes. Commented 2 days ago
  • @WeatherVane but for the beginner is not a problem (not EOF) Commented 2 days ago
  • 2
    @0___________ is a beginner's char able to hold EOF? Commented 2 days ago

3 Answers 3

1

After this line

workspace_file->flc = realloc(workspace_file->flc, (line+2)*sizeof(char*));

the added pointer has an indeterminate value. So using realloc in this statement

workspace_file->flc[line] = realloc(workspace_file->flc[line], (pos+2)*sizeof(char));

results in undefined behavior.

Pay attention to that in general the function realloc can return a null pointer. So you should use an intermediate pointer to store the result of a call of realloc and if it is not equal to null to assign it to pointers workspace_file->flc and workspace_file->flc[line]. Otherwise you will have at least a memory leak.

0

In the else clause you extend the number of lines you're storing, but you don't initialize the new line that you're going to write to. So when you try to write the first character of the next line, you're dereferencing an invalid pointer.

workspace_file->flc = realloc(workspace_file->flc, (line+2)*sizeof(char*));
line++;
pos = 0;
workspace_file->flc[line] = malloc(1);    // set up the next line
0

There are multiple problems in the posted fragment:

  • you do not test for fopen success: the program will crash if the file cannot be opened.
  • fileInputBuffer should have type int to accommodate for all byte values and the special negative value EOF.
  • when you reallocate the array of char*, you do not allocate a new empty line at the end of the array.
  • you do not check for memory allocation errors.
  • the variable names are too long, making the code harder to read.

Here is a modified version:

#include <error.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

bool read_file(MyStruct *wp) {
    FILE *fp = fopen(wp->filename, "r");
    wp->flc = NULL;
    wp->len = 0;
    if (fp == NULL) {
        fprintf(stderr, "cannot open %s: %s\n", wp->filename, strerror(errno));
        return false;
    }
    int line = 0;
    int pos = 0;
    wp->flc = malloc(1 * sizeof(char *));
    wp->flc[0] = malloc(1);
    int c;
    while ((c = fgetc(fp)) != EOF) {
        if (c == '\n') {
            wp->flc[line][pos] = '\0';
            line++;
            wp->flc = realloc(wp->flc, (line + 1) * sizeof(char *));
            pos = 0;
            wp->flc[line] = malloc(1);
        } else {
            wp->flc[line][pos] = (char)c;
            pos++;
            wp->flc[line] = realloc(wp->flc[line], pos + 1);
        }
    }
    if (pos) {
        // last line without a trailing newline
        wp->flc[line][pos] = '\0';
        line++;
    } else {
        // free the empty line
        free(wp->flc[line]);
    }
    wp->len = line;
    fclose(fp);
    return true;
}
1
  • @4386427 Good point, answer amended Commented 2 days ago

Your Answer

By clicking β€œPost Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.