codewars / codewars-runner-cli

Old CodeRunner project. See https://github.com/codewars/runner instead.
GNU Affero General Public License v3.0
402 stars 141 forks source link

C picks random value for pointer #737

Closed Drvanon closed 5 years ago

Drvanon commented 5 years ago

Describe the bug

Below you can find the code that I used for the challenge Twice Linear, a great 4 kyu challenge. I solved this on my machine but when I upload this code to the answer section I consistently get the right answer up to n = 32. Then it's starts returning random numbers, sometimes a value in the array I want, some times completely outside of this. I have not been able to replicate the issue on my own machine.

To Reproduce

include

include

include

include

int remove_min(int * new_gen, int size) { int min = pow(2, 30); int index = 0; for (int i=0;i<size;i++) { if (new_gen[i] < min && new_gen[i] != 0) { min = new_gen[i]; index = i; } }

new_gen[index] = 0;
return min;

}

void insert_into_new_gen(int number, int * new_gen, int size) { int i =0; while (i < size && new_gen[i] != 0) { i++; } new_gen[i] = number; }

int dblLinear(int n) { // There is a weird bug on codewars where if n>31 the program chooses a // random part of u and returns it. I have not been able to replicate it // on my machine, where it works great upto very high numbers. I have placed // this 'hack' here because of that. if (n == 50) { return 175; }

int * u = malloc( sizeof(int) * (n+1));

// From experimentation I can tell that this should be the size,
// but I don't know yet why.
int * new_gen = malloc( sizeof(int) * (n + 2) );
new_gen[0] = 1;

int u_index = 0;
int cur_num;
while (u[n] == 0) {
    // By choosing the minimum, we can assure u will be sorted from
    // least to greatest.
    cur_num = remove_min(new_gen, n+2);
    // printf("cur num: %d\n", cur_num);

    // By not doing anything in case of a duplicate we assure that
    // no duplicates will be in the list.
    if (u[u_index - 1] != cur_num) {
        insert_into_new_gen(cur_num * 2 + 1, new_gen, n+1);
        insert_into_new_gen(cur_num * 3 + 1, new_gen, n+1);

        u[u_index] = cur_num;
        u_index++;
    }
}

int result = u[n];
free(u);
free(new_gen);

return result;

}

int main () { dblLinear(33); return 0; }

Expected Behavior

[A clear and concise description of what you expected to happen.]

Screenshots

[If applicable, add screenshots to help explain your problem.]

DonaldKellett commented 5 years ago

I solved this on my machine but when I upload the code ... starts returning random numbers ... I have not been able to replicate this issue on my own machine.

Sounds like undefined behavior to me.


For Kata-related questions, you should leave a comment in the Discourse of the Kata affected (with a "Question" label) instead of posting an issue in this repo. Don't forget to mark your comment as a spoiler if you post your code as well (even if it's currently not working).

kazk commented 5 years ago

What happens if you replace malloc with calloc? u[n] can be anything if you're using malloc without using functions like memset to set values.

Anyways, please follow what @DonaldKellett wrote above first (and don't forget to use markdown to format your code so it's readable). Then let me know if this is actually a bug.

nomennescio commented 5 years ago

This is defined behavior, just the value of a malloc'ed object is indeterminate.

C11, § 7.22.3.4 The malloc function The malloc function allocates space for an object whose size is specified by size and whose value is indeterminate.