0

Link to the question: https://www.codewars.com/kata/54d496788776e49e6b00052f/train/cpp

Guys could you please help me figure out why my solution worked completely fine in Visual Studio but not in Codewars?

The error in Codewars is as follows:

UndefinedBehaviorSanitizer:DEADLYSIGNAL
==1==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0x000000000000 (pc 0x000000425dce bp 0x000000000000 sp 0x7ffca477d200 T1)
==1==The signal is caused by a READ memory access.
==1==Hint: address points to the zero page.
==1==WARNING: invalid path to external symbolizer!
==1==WARNING: Failed to use and restart external symbolizer!
    #0 0x425dcd  (/workspace/test+0x425dcd)
    #1 0x425a0a  (/workspace/test+0x425a0a)
    #2 0x42b951  (/workspace/test+0x42b951)
    #3 0x429b5e  (/workspace/test+0x429b5e)
    #4 0x42958d  (/workspace/test+0x42958d)
    #5 0x42927b  (/workspace/test+0x42927b)
    #6 0x42e235  (/workspace/test+0x42e235)
    #7 0x4287fd  (/workspace/test+0x4287fd)
    #8 0x7f833e965bf6  (/lib/x86_64-linux-gnu/libc.so.6+0x21bf6)
    #9 0x404a29  (/workspace/test+0x404a29)

UndefinedBehaviorSanitizer can not provide additional info.
==1==ABORTING

*In Codewars, the test ran fine, but the attempt didn't, the calculations were all correct, but when it went to question number 3, the error strikes and it doesn't continue on to solving questions anymore.

The code I used in Codewars:

#include <iostream>
#include <vector>
#include <string>
#include <tuple>
#include <chrono>
#include <thread>

//Sum by Factors(Finished)
//====================


using namespace std;
class SumOfDivided
{
    vector<int> SuitablePrimeArray;

    string getSumOfNumbersByPrimeFactorAndMakeBracket(int PrimeNumber, vector<int>& I);//for createBrackets
    tuple<int, vector<int>> findSmallestNumberInArrayAndDeleteIt(vector<int> Numbers);//for sortAscendingly
public:
    int findLargestNumberInArray(vector<int> Numbers);
    vector<int> findPrimeNumbersTill(int End);
    vector<int> findPrimeFactorsFromArray(vector<int> PrimeArr, vector<int> Numbers);
    void printVectorArray(vector<int> array);
    string executeKata(vector<int> Numbers);
    string createBrackets(vector<int> FinalPrimeArr, vector<int>& Numbers);
    vector<int> sortAscendingly(vector<int> input);
    
    vector<int> generateRandomVector(int NumberCount, int minimum, int maximum);
    int generateRandomNumber(int minimum, int maximum);
  
    static string sumOfDivided(vector<int> &lst);
};

string SumOfDivided::sumOfDivided(vector<int> &lst){
    SumOfDivided test;
    return test.executeKata(lst);
}




string SumOfDivided::executeKata(vector<int> Numbers) {
    cout << "The array: " << endl;
    printVectorArray(Numbers);
    cout << endl;

    int TheLargestNumber = findLargestNumberInArray(Numbers);
    cout << "The largest number from this array: " << endl << TheLargestNumber << endl;
    cout << endl;

    cout << "All the prime factors of this array: " << endl;
    //printVectorArray(findFactorsFromArray(findPrimeNumbersTill(TheLargestNumber), Numbers));
    SuitablePrimeArray = findPrimeFactorsFromArray(findPrimeNumbersTill(TheLargestNumber), Numbers);
    printVectorArray(SuitablePrimeArray);
    cout << endl;

    string Answer = createBrackets(SuitablePrimeArray, Numbers);
    cout << "Answer for the 4 kyu Kata(Sum by Factors): " << endl << Answer << endl;

    return Answer;
}

int SumOfDivided::findLargestNumberInArray(vector<int> Numbers) {
    int largest, i, pos;
    largest = Numbers[0];
    for (i = 1; i < Numbers.size(); i++) {
        if (Numbers[i] > largest) {
            largest = Numbers[i];
            pos = i;
        }
    }
    return largest;
}

vector<int> SumOfDivided::findPrimeNumbersTill(int End) {
    vector<int> PrimeArr;
    //PrimeArr.reserve(50);
    int position = 0;
    int n = 2;
    while (position < End) {
        bool isPrime = true;
        for (int i = 2; i <= n / 2; ++i) {
            if (n % i == 0) {
                isPrime = false; break;
            }
        }
        //if (isPrime){PrimeArr[position] = n; position++;}
        if (isPrime) {
            PrimeArr.push_back(n);
            position++;
        }
        n++;
    }
    /*
    for (int i = 0; i < position; i++) {
        cout << PrimeArr[i] << ",";
    }
    */
    //printVectorArray(PrimeArr);
    //cout << endl;
    return PrimeArr;
}

vector<int> SumOfDivided::findPrimeFactorsFromArray(vector<int> PrimeArr, vector<int> Numbers) {
    /*
    for (int i = 0; i < PrimeArr.size(); i++) {
        cout << PrimeArr[i] << ", ";
    }
    */
    vector<int> FinalPrimeFactorArray;
    int position = 0;
    for (int i = 0; i < Numbers.size(); i++) {
        for (int j = 0; j < PrimeArr.size(); j++) {
            if (Numbers[i] % PrimeArr[j] == 0 && find(FinalPrimeFactorArray.begin(), FinalPrimeFactorArray.end(), PrimeArr[j]) == FinalPrimeFactorArray.end()) {
                FinalPrimeFactorArray.push_back(PrimeArr[j]); position++;
            }
        }
    }
    
    return sortAscendingly(FinalPrimeFactorArray);;
}

void SumOfDivided::printVectorArray(vector<int> array) {
    for (int i = 0; i < array.size(); i++) {
        cout << array[i] << ",";
    }
    cout << endl;
}

//=======================the code below is from part of my codewar unfinished scripts

string SumOfDivided::createBrackets(vector<int> FinalPrimeArr, vector<int>& Numbers) {
    string Answer;
    vector<int> I;
    for (int i = 0; i < Numbers.size(); i++) {
        I.push_back(0);
        I[i] = Numbers[i];
        //cout << "push back x" << i + 1 << endl;
    }
    for (int i = 0; i < FinalPrimeArr.size(); i++) {
        Answer += getSumOfNumbersByPrimeFactorAndMakeBracket(FinalPrimeArr[i], I);
    }
    return Answer;
}

string SumOfDivided::getSumOfNumbersByPrimeFactorAndMakeBracket(int PrimeNumber, vector<int>& I) {
    int Sum = 0;
    for (int i = 0; i < I.size(); i++) {
        //add this number to the total if the current number is divisible by the prime number
        if (I[i] % PrimeNumber == 0)Sum += I[i];
    }
    //cout << "The sum of numbers divisible by the prime number " << PrimeNumber << " is " << Sum << endl; 
    string temp = "(" + to_string(PrimeNumber) + " " + to_string(Sum) + ")";
    //cout << temp << endl;
    return temp;
}

//=====================SORT ASCENDINGLY

tuple<int, vector<int>> SumOfDivided::findSmallestNumberInArrayAndDeleteIt(vector<int> Numbers) {
    int smallest, i, pos(0);
    smallest = Numbers[0];
    for (i = 1; i < Numbers.size(); i++) {
        if (Numbers[i] < smallest) {
            smallest = Numbers[i];
            pos = i;
        }
    }
    Numbers.erase(Numbers.begin() + pos);
    return make_tuple(smallest, Numbers);
}

vector<int> SumOfDivided::sortAscendingly(vector<int> input) {
    vector<int> output;
    int CurrentLargestNumber;
    int End = input.size();
    for (int i = 0; i < End; i++) {
        tie(CurrentLargestNumber, input) = findSmallestNumberInArrayAndDeleteIt(input);
        //cout << CurrentLargestNumber << ", ";
        output.push_back(CurrentLargestNumber);
    }
    return output;
}

//=============================RANDOM GENERATION

vector<int> SumOfDivided::generateRandomVector(int NumberCount, int minimum, int maximum) {
    vector<int> vecRandomValues;
    int i = 0, randValue = 0;
    srand(time(NULL));
    while (i < NumberCount) {
        randValue = rand() % (maximum - minimum + 1) + minimum;
        vecRandomValues.push_back(randValue);
        i++;
    }
    return vecRandomValues;
}

int SumOfDivided::generateRandomNumber(int minimum, int maximum) {
    return rand() % (maximum - minimum + 1) + minimum;
}

*And my code in Visual Studio, basically the same but with random number generation to randomly test it, I can run it 5000 times in 10 seconds and no error occurred.

The Code I used in Visual Studio:

//Sum by Factors(unFinished)
//====================
#include <iostream>
#include <vector>
#include <string>
#include <Windows.h>
#include "RandomNumber.h"
#include "Bubblesort.h"

/*
Sum by prime factors:
    example:
    list of number: 12, 15
    answer: (2, 12), (3, 27), (5, 15)

    explaination for generating answers:
    ( (all prime factors from the list of numbers in ascending order),(sum of all the nominators of this prime factor on the left) )
*/

using namespace std;

class SumOfDivided
{
    vector<int> SuitablePrimeArray;
    string getSumOfNumbersByPrimeFactorAndMakeBracket(int PrimeNumber, vector<int>& I);//for createBrackets
public:
    int findLargestNumberInArray(vector<int> Numbers);
    vector<int> findPrimeNumbersTill(int End);
    vector<int> findPrimeFactorsFromArray(vector<int> PrimeArr, vector<int> Numbers);
    void printVectorArray(vector<int> array);
    string executeKata(vector<int> Numbers);
    string createBrackets(vector<int> FinalPrimeArr, vector<int>& Numbers);
};

int main() {
    vector<SumOfDivided> list;
    for (int i = 0; i < 5000; i++) {
        SumOfDivided test;
        list.push_back(test);
        cout << "attempt " << i + 1 << endl;
        test.executeKata(RandomNumber::generateRandomVector(RandomNumber::generateRandomNumber(2, 10), 100, 1000));
        cout << "=========================================" << endl;
        cout << endl;
    }
    /*
    for (int i = 0; i < 10; i++) {
        SumOfDivided* test = new SumOfDivided;
        RandomNumber* a = new RandomNumber;
        cout << "attempt " << i + 1 << endl;
        test->executeKata(a->generateRandomVector(a->generateRandomNumber(2, 10), 100, 1000));
        cout << "=========================================" << endl;
        cout << endl;
        //delete test, a;
    }
    */
    //vector<vector<int>> Numbers = { { 12,15,24,18,2525 }, { 44,787,84,75,255,7543,373,6746,473 }, { 360,777,689,426,999 } };
    //test.executeKata(Numbers[0]);
    ////std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    //cout << "============" << endl;
    //test.executeKata(Numbers[1]);
    ////std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    //cout << "============" << endl;
    //test.executeKata(Numbers[2]);
}

string SumOfDivided::executeKata(vector<int> Numbers) {
    cout << "The array: " << endl;
    printVectorArray(Numbers);
    cout << endl;

    int TheLargestNumber = findLargestNumberInArray(Numbers);
    cout << "The largest number from this array: " << endl << TheLargestNumber << endl;
    cout << endl;

    cout << "All the prime factors of this array: " << endl;
    //printVectorArray(findFactorsFromArray(findPrimeNumbersTill(TheLargestNumber), Numbers));
    SuitablePrimeArray = findPrimeFactorsFromArray(findPrimeNumbersTill(TheLargestNumber), Numbers);
    printVectorArray(SuitablePrimeArray);
    cout << endl;

    string Answer = createBrackets(SuitablePrimeArray, Numbers);
    cout << "Answer for the 4 kyu Kata(Sum by Factors): " << endl << Answer << endl;

    return Answer;
}

int SumOfDivided::findLargestNumberInArray(vector<int> Numbers) {
    int largest;
    unsigned i, pos;
    largest = Numbers[0];
    for (i = 1; i < Numbers.size(); i++) {
        if (Numbers[i] > largest) {
            largest = Numbers[i];
            pos = i;
        }
    }
    return largest;
}

vector<int> SumOfDivided::findPrimeNumbersTill(int End) {
    vector<int> PrimeArr;
    //PrimeArr.reserve(50);
    int position = 0;
    int n = 2;
    while (position < End) {
        bool isPrime = true;
        for (int i = 2; i <= n / 2; ++i) {
            if (n % i == 0) {
                isPrime = false; break;
            }
        }
        //if (isPrime){PrimeArr[position] = n; position++;}
        if (isPrime) {
            PrimeArr.push_back(n);
            position++;
        }
        n++;
    }
    /*
    for (int i = 0; i < position; i++) {
        cout << PrimeArr[i] << ",";
    }
    */
    //printVectorArray(PrimeArr);
    //cout << endl;
    return PrimeArr;
}

vector<int> SumOfDivided::findPrimeFactorsFromArray(vector<int> PrimeArr, vector<int> Numbers) {
    /*
    for (int i = 0; i < PrimeArr.size(); i++) {
        cout << PrimeArr[i] << ", ";
    }
    */
    vector<int> FinalPrimeFactorArray;
    unsigned position = 0;
    for (unsigned i = 0; i < Numbers.size(); i++) {
        for (unsigned j = 0; j < PrimeArr.size(); j++) {
            if (Numbers[i] % PrimeArr[j] == 0 && find(FinalPrimeFactorArray.begin(), FinalPrimeFactorArray.end(), PrimeArr[j]) == FinalPrimeFactorArray.end()) {
                FinalPrimeFactorArray.push_back(PrimeArr[j]); position++;
            }
        }
    }
    
    return Bubblesort::sortAscendingly(FinalPrimeFactorArray);;
}

void SumOfDivided::printVectorArray(vector<int> array) {
    for (unsigned i = 0; i < array.size(); i++) {
        cout << array[i] << ",";
    }
    cout << endl;
}

//=======================the code below is from part of my codewar unfinished scripts

string SumOfDivided::createBrackets(vector<int> FinalPrimeArr, vector<int>& Numbers) {
    string Answer;
    vector<int> I;
    for (unsigned i = 0; i < Numbers.size(); i++) {
        I.push_back(0);
        I[i] = Numbers[i];
        //cout << "push back x" << i + 1 << endl;
    }
    for (unsigned i = 0; i < FinalPrimeArr.size(); i++) {
        Answer += getSumOfNumbersByPrimeFactorAndMakeBracket(FinalPrimeArr[i], I);
    }
    return Answer;
}

string SumOfDivided::getSumOfNumbersByPrimeFactorAndMakeBracket(int PrimeNumber, vector<int>& I) {
    int Sum = 0;
    for (unsigned i = 0; i < I.size(); i++) {
        //add this number to the total if the current number is divisible by the prime number
        if (I[i] % PrimeNumber == 0)Sum += I[i];
    }
    //cout << "The sum of numbers divisible by the prime number " << PrimeNumber << " is " << Sum << endl; 
    string temp = "(" + to_string(PrimeNumber) + " " + to_string(Sum) + ")";
    //cout << temp << endl;
    return temp;
}

*Lastly, when I checked the MSI afterburner, even solving 10000 solutions in a row doesn't use much ram, and it stays steady, not going up, so I don't think it's codewar running out of memory :)

Tommy Lau
  • 25
  • 6
  • 6
    there's a lot of code there and a lot of differences, please show a [mre] – Alan Birtles Oct 22 '21 at 16:21
  • 1
    `smallest = Numbers[0];` and `largest = Numbers[0];` would be undefined behavior if the Numbers was empty. – drescherjm Oct 22 '21 at 16:22
  • 1
    Replace `[index]` with `.at(index)` so you'll get an exception on out-of-range access. `smallest = Numbers[0]; ` and `largest = Numbers[0]; ` seems the potential culprit. – alagner Oct 22 '21 at 16:45
  • You should 't need different code in Codewars and Visual Studio. That you have different code suggests you're misunderstanding something. – user4581301 Oct 22 '21 at 16:49
  • A note about `srand`: You only want to call it once. Every time you call it, you restart the random number generator with what you hope will be a new seed. Since the code uses `time` to provide the seed multiple calls to `srand` within the resolution of `time`, typically one second, the program will use the same seed and repeat the generated sequence. There are a few cases where restarting the number generator is necessary, but typically they only crop up in cases where `rand` isn't up to producing the randomness necessary. – user4581301 Oct 22 '21 at 16:56
  • no, the only thing different is that, i changed "string sumOfDivided" into "int main", and added random number generation so that i will have some inputs when I test it in Visual Studio. I haven't heard of any sanitizers before, I don't really know what they are. – Tommy Lau Oct 22 '21 at 19:55
  • Sanitizer are there to warn you that your code contains at least some Undefined Behavior. My first comment gave you 2 examples where your code could access elements of the array that may not exist. You probably want to change your code to throw an exception if the vector passed to `findSmallestNumberInArrayAndDeleteIt` is empty. Same goes for `findLargestNumberInArray()` – drescherjm Oct 23 '21 at 18:48

1 Answers1

1

The error message you receive comes form the undefined behavior sanitizer. This is an optional feature that can be enabled with compiler flags. It seems that it is enabled in the Codewars environment but not in your Visual Studio environment.

Your code may produce the correct result, but the crash indicates that this is merely a coincidence because you invoke undefined behavior somewhere. Try narrowing it down before asking any more questions.

Usually, it will give a proper backtrace with filenames and line numbers, however, it seems that something is configured incorrectly and you only have addresses in the backtrace:

#0 0x425dcd  (/workspace/test+0x425dcd)
#1 0x425a0a  (/workspace/test+0x425a0a)
#2 0x42b951  (/workspace/test+0x42b951)
#3 0x429b5e  (/workspace/test+0x429b5e)
#4 0x42958d  (/workspace/test+0x42958d)
#5 0x42927b  (/workspace/test+0x42927b)
#6 0x42e235  (/workspace/test+0x42e235)
#7 0x4287fd  (/workspace/test+0x4287fd)
#8 0x7f833e965bf6  (/lib/x86_64-linux-gnu/libc.so.6+0x21bf6)
#9 0x404a29  (/workspace/test+0x404a29)

This part of the error message tells you what is wrong, not sure how to fix it though:

==1==WARNING: invalid path to external symbolizer!
==1==WARNING: Failed to use and restart external symbolizer!
asynts
  • 2,213
  • 2
  • 21
  • 35
  • The lack of symbols may be deliberate on the part of the judge to make the challenger work harder. Good to see the judges finally rejecting flawed code that passed the test mostly by luck. – user4581301 Oct 22 '21 at 17:00
  • sorry, but i don't really know where I dereferenced a null pointer – Tommy Lau Oct 22 '21 at 18:29
  • It may not even be something that you do, but something that the address sanitizer inserted for you, not sure how much freedom the address sanitizer has. – asynts Oct 22 '21 at 19:30