0

Compiles without warnings or errors, just the following code crashes when I try to either read from or write to the matrix constValues.

It needs to be passed to another function to be read from also; the function createOutputLine.

How can I point to the data held correctly so it can be modified and read from? Thanks.

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

void createOutputFile(FILE*, int, char**);
char createOutputLine(int, int, char*, char**);

int main(int argc, char **argv) {
    int removeComments = 0;
    FILE *file;
    if (argc > 1 && strcmp(argv[1], "-i") == 0) {
        if (argc > 2) {
            if (!(file = fopen(argv[2], "r"))) {
                printf("Error: file not found");
                return -1;
            }
        }
        else {
            printf("Error: no file specified");
            return -1;
        }
    }
    else {
        printf("Error: command requires -i");
        return -2;
    }
    createOutputFile(file, argc, argv);
    fclose(file);
}

void createOutputFile(FILE *file, int argc, char **argv) {
    fseek(file, 0, SEEK_SET);
    char *data = (char*)malloc(2000);
    FILE *header;
    char name[20];
    char *token = strtok(argv[2], ".");
    strcpy(name, strcat(token, ".o"));
    FILE *output = fopen(name, "w");
    char constNames[10][15];
    char **constValues[10][10];
    int constsStored = 0;
    while (fgets(data, 2000, file) != NULL) {
        for (int i = 0; i < strlen(data); i++) {
            int c = i;
            bool linePrinted = false;
            if (data[i] == '#' && data[i + 1] == 'd') {
                for (c = i; c <= i + 7; c++) {
                    data[c] = '\0';
                } int ch = 0;
                while (data[c] != ' ') {
                    constNames[constsStored][ch] = data[c];
                    data[c] = '\0';
                    ch++;
                    c++;
                } ch = 0;
                while (data[c] != '\n') {
                    **constValues[constsStored][ch] = data[c]; //this line crashes
                    data[c] = '\0';
                    ch++;
                    c++;
                }
                if (data[c] == '\n') data[c] = '\0';
                constsStored++;
            }
            for (int ch = 0; ch <= constsStored; ch++) {
                if (data[i] == constNames[ch][0]) {
                    int ch2 = i + 1;
                    int ch3 = 1;
                    bool isConst = false;
                    while (data[ch2] != ' ') {
                        if (data[ch2] == constNames[ch][ch3] && isConst == false) isConst = true;
                        ch2++;
                        ch3++;
                    }
                    if (isConst || data[i + 1] == ' ') {
                        char line[200];
                        line[200] = createOutputLine(i, ch, data, **constValues);
                        fprintf(output, "%c", line[200]);
                        linePrinted = true;
                    }
                }
            }
            if (!linePrinted)
                fprintf(output, "%c", data[i]);
        }
    }
    fclose(output);
    free(data);
}

char createOutputLine(int i, int constElem, char *data, char **constValues) {
    int ch = i;
    int ch2 = 0;
    char temp[200];
    while (data[ch] != '\n' && data[ch] != ' ' && data[ch] != ';') {
        temp[ch2] = data[ch];
        printf("%c", data[ch]);
        ch++;
        ch2++;
    }
    char line[200];
    ch2 = 0;
    for (ch = i; ch <= sizeof(data); ch++) {
        line[ch2] = data[ch];
        ch2++;
    }
    for (ch = 0; ch <= 10; ch++) {
        line[ch2] = constValues[constElem][ch];
        ch2++;
    }
    for (ch = 0; ch <= sizeof(temp); ch++) {
        line[ch2] = temp[ch];
        ch2++;
    }
    line[ch2 + 1] = '\n';
    return line[200];
}
  • Also, this is the kind of thing you should narrow down with a debugger first. – Federico klez Culloca Mar 01 '19 at 13:23
  • 1
    `warning: array index 200 is past the end of the array (which contains 200 elements)` If you aren't getting any warnings, then you either need to learn how to use your compiler correctly, or you need to get a better compiler. – user3386109 Mar 01 '19 at 13:26
  • anyway is this `**constValues[constsStored][ch]` you trying to make the line bold or is that what is in your actual source code? – Federico klez Culloca Mar 01 '19 at 13:27
  • Please provide a minimal input file that triggers the error and tell us which command line should me used to invoke the program. – Jabberwocky Mar 01 '19 at 13:29
  • 2
    2D arrays have nothing to do with ` char **constValues[10][10];`, which in turn has nothing to do with `char **constValues`. See [Correctly allocating multi-dimensional arrays](https://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays). – Lundin Mar 01 '19 at 13:32
  • 1
    Note that `for (ch = i; ch <= sizeof(data); ch++)` does not give the array size of a function parameter because it is a pointer, unlike `for (ch = 0; ch <= sizeof(temp); ch++)` further down, where the array is local. Note there is a bounds error in this loop anyway it should be `ch < sizeof(temp)`. Maybe you should have used `strlen` in both cases. . . – Weather Vane Mar 01 '19 at 13:35
  • . . . that is function `createOutputLine` which returns `char` type yet `return line[200];` is out of array bounds. If you intended to return `char *` the array pointer, that is no good either as `char line[200]` is local and goes out of scope. – Weather Vane Mar 01 '19 at 13:38

1 Answers1

1

A pointer shall point to an object before it can be derefenced. Full stop.

char **constValues[10][10]; just declares an 2D array of pointers to pointers to characters. And as it is an automatic array (neither statically nor dynamically allocated), its pointers are just uninitialized.

When you late use **constValues[constsStored][ch] = data[c];, you try to dereference an uninitialized pointer which is explicitely Undefined Behaviour. You are lucky to get an immediate crash, because UB consequences can be apparently unrelated problems.

The normal way is to declare arrays of objects, and use the addresses of those objects for pointers.

That's not all: C arrays are not first class citizens. You cannot assign to array, nor return it from a function. So this is plain wrong:

    char line[200];
    line[200] = createOutputLine(i, ch, data, **constValues);

It just assigns the unique character returned by the function past the end of the array!

So is this:

char line[200];
...
return line[200];

It does not return an array (C does not allow it) but the value of the byte that happens to live past the array.

I am sorry, but there are too many errors for me to fix them is such a long program.

You may find C hard and ask for help. But build small code containing only what you want to work on. And only when those small pieces work correctly, try to assemble them in a larger program.

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252