Home > Software engineering >  Error passing by reference when making os
Error passing by reference when making os

Time:04-27

I am making an os and have booted into a 64 bit kernel made in c. I have made a print function which is working and am trying to make a function to convert hex values to string so I can print them. My code is causing boot loops, yet when I compile the exact same code to run normally in linux it works perfectly. The relevant code:

int logarithm(double value, int base, int* output) {
    int i = 0;

    while (value > 1) {
        value /= base;
        i  ;
    }

    *output = i;
}

int power(int value, int power, int* output) {
    if (power == 0) {
        value = 1;
    } else {
        for (int i = 0; i < (power - 1); i  ) {
            value *= value;
        }
    }

    *output = value;
}

void hexToStr(unsigned int hex, char** string) {
    int hexLength = 0;
    logarithm((double)hex, 16, &hexLength);
    char output[hexLength];
    output[hexLength] = 0;

    int powerValue = 0;
    for (int i = 0; i < hexLength; i  ) {
        power(16, i, &powerValue);
        output[hexLength - i - 1] = (hex & (powerValue * 15)) / powerValue   '0';
    }

    *string = output;
}

If I change the hexToStr() function code to this (removing the need for logarithm() and power() functions by hardcoding values for the string), it works in both linux and my kernel:

void hexToStr(unsigned int hex, char** string) {
    int hexLength = 10;
    char output[hexLength];
    output[hexLength] = 0;

    int powerValue = 0;
    for (int i = 0; i < hexLength; i  ) {
        output[hexLength - i - 1] = 'A';
    }

    *string = output;
}

Any suggestions as to why this would happen?

CodePudding user response:

The presented code invokes undefined behavior. For example let's consider this function

void hexToStr(unsigned int hex, char** string) {
    int hexLength = 10;
    char output[hexLength];
    output[hexLength] = 0;

    int powerValue = 0;
    for (int i = 0; i < hexLength; i  ) {
        output[hexLength - i - 1] = 'A';
    }

    *string = output;
}

In this assignment statement:

    output[hexLength] = 0;

there is written data outside the array because the valid range of indices is [0, hexLength).

Or the function sets a pointer passed to the function by reference to the local array output that will not be alive after exiting the function. So the returned pointer will have an invalid value.

Another example the result value of the function power when the parameter value is equal to 3 and the parameter power is equal to 3 will be equal to 81 instead of 27 due to the assignment statement in this for loop.

    for (int i = 0; i < (power - 1); i  ) {
        value *= value;
    }

Moreover the function returns nothing though its return type is not void.

int power(int value, int power, int* output) {

Also this expression

(hex & (powerValue * 15)) / powerValue   '0'

does not make a sense.

CodePudding user response:

Needed to enable SSE unit to work with floats and doubles. As well as change how values are passed back. Working code:

void log(float value, float base, uint64_t* output) {
    uint64_t i = 0;

    while (value >= 1) {
        value /= base;
        i  ;
    }

    *output = i;
}

void pow(uint64_t value, uint64_t exponent, uint64_t* output) {
    uint64_t result = 1;

    for (uint64_t i = 0; i < exponent; i  ) {
        result = result * value;
    }

    *output = result;
}

void hexToStr(uint64_t hex, char* output) {
    uint8_t hexLen = 16;
    log((float)hex, (float)16, &hexLen);
    char result[hexLen   3];
    result[0] = '0';
    result[1] = 'x';
    result[hexLen   2] = 0;

    uint64_t powerValue = 1;
    for (uint8_t i = 0; i < hexLen; i  ) {
        pow(16, i, &powerValue);
        result[hexLen - i   1] = (hex & (uint64_t)(powerValue * (uint64_t)15)) / powerValue   '0';
    }

    for (uint8_t i = 0; i < hexLen   3; i  ) {
        switch(result[i]) {
            case ':':
                result[i] = 'A';
                break;
            case ';':
                result[i] = 'B';
                break;
            case '<':
                result[i] = 'C';
                break;
            case '=':
                result[i] = 'D';
                break;
            case '>':
                result[i] = 'E';
                break;
            case '?':
                result[i] = 'F';
                break;
        }
        output[i] = result[i];
    }
}
  • Related