1

I was reading an article or post online found here: Eli Bendersky's Website : Binary Representation of Big Numbers and came across a function so I decided to test it in my IDE. The function compiles & builds but when I run the code it wants to throw an exception : write access violation.

Here is the function:

/* Note: in and out may be the same string,
   it will still work OK
*/
void longdiv2(const char* in, char* out)
{
    int carry = 0;

    while (*in)
    {
        int numerator = *in++ - '0';
        numerator += carry;

        carry = (numerator % 2) == 0 ? 0 : 10;
        *out++ = '0' + (numerator / 2);
    }

    *out = '\0';
}

I use it like this:

#include <iostream>

int main() {
    char* value = "12345";
    char* binResult = '\0';

    longdiv2( value, binResult );

    std::cout << *binResult << std::endl;

    std::cout << "\nPress any key and enter to quit." << std::endl;
    char q;
    std::cin >> q;

    return 0;
}

The access violation is thrown on this line:

 *out++ = '0' + (numerator / 2);

The violation is stating that out was nullptr.


I'm running this on MS Visual Studio 2017 CE on an Intel Quad Core Extreme running Win7 Home Premium x64 - compiled and built as an x86 console application.

[Note:] I tagged this with both C & C++: I tagged it like this because the article mentioned that they written it for C, however I'm using the same function in C++.

Barmar
  • 741,623
  • 53
  • 500
  • 612
Francis Cugler
  • 7,788
  • 2
  • 28
  • 59

2 Answers2

3

*out++ is accessing pointer which is not pointing to valid memory. That's why you get access violation when de-referencing it, after having an illegal memory access. This would work

char binResult[10];

Here basically when you pass it to the function you would be passing the decayed char* and make changes to it.

Alternatively this will also do

binResult =(char*) malloc(10);
if( binResult == NULL){
  perror("Malloc Failed");
}

In detail, the problem boils down to that the pointer was not pointing to any buffer where you can store the results. When you try to access that, you were basically trying to write to some memory that you don't even have permission to. (Write access violation). That's why you get the error.

To be even more clear it shouldn't come as suprise when you set pointer value to \0 and then try to access it. On the first iteration itself it causes the nullptr access, causing the error.

Full C code:

#include<stdio.h>
void longdiv2(const char* in, char* out)
{
    int carry = 0;

    while (*in)
    {
        int numerator = *in++ - '0';
        numerator += carry;

        carry = (numerator % 2) == 0 ? 0 : 10;
        *out++ = '0' + (numerator / 2);
    }

    *out = '\0';
}


int main(void) {
    char* value = "12345";
    char binResult[10];

    longdiv2( value, binResult );

    printf("%s\n",binResult);
    return 0;
}

This outputs

06172

Code compiled using gcc 6.3.0: gcc -Wall -Werror progname.c

A C++ solution would be something like

/* Here in and out shouldn't point to same thing */

#include <iostream>
#include <string>

void longdiv2(std::string in, std::string& out)
{
    int carry = 0;

    for(auto x:in)
    {
        int numerator = x - '0';
        numerator += carry;

        carry = (numerator % 2) == 0 ? 0 : 10;
        out.push_back( '0' + (numerator / 2));
    }

}

int main(void) {
    std::string value = "12345";
    std::string binResult;

    longdiv2( value, binResult );

    std::cout<<binResult<<std::endl;
    return 0;
}
user2736738
  • 30,591
  • 5
  • 42
  • 56
1

Change the following:

char* binResult = '\0';

to:

char binResult[10] {};
SoronelHaetir
  • 14,104
  • 1
  • 12
  • 23
  • (which should not even have compiled): no it's an integral value. Maybe a warning, but effectively sets the pointer to 0 – Jean-François Fabre Dec 29 '17 at 09:07
  • Why do you think `char* binResult = '\0';` shouldn't compile? It's perfectly valid. – user0042 Dec 29 '17 at 09:07
  • I already stated in my question that it "DOES" compile & "Builds"; it was throwing an exception at runtime. I know what the runtime exception is: my C is a little rusty and was having a hard time remembering what was causing it with `C` style strings over preferred `C++` `std::string`... – Francis Cugler Dec 29 '17 at 09:34