-3

I am working on a C method to find the inverse of a number mod n, and it works perfectly fine when for example I call this method with 6.0 and 65537.0, it gives me the correct result, even when showing a warning for dereferencing the pointer, however when I call it with a = 3.0 and n = 177408180034551.0 visual studio break in the line origNums[0] = n; and gives me error

0xC0000005: Access violation writing location 0x00000000.

I understand that with smaller arrays like size 5 or what not, I could simply initialize my array with something like origNums = {1,2,3,4,5} but because of the size of my modulo that is simply not possible for a human to write and putting a for loop to fill the arrays would give the same access violation. So what other solution is there to this issue? And more importantly why is there no warning for nums[0] = rightVal; ? if they both had a warning it would seem like it is a common issue but in visual studio only the first assignment is underlined with a warning.

double inverseModN(double a, double n)
{
    double* nums = (double*) malloc((n) * sizeof(double));
    double* origNums = (double*)malloc((n) * sizeof(double));
    *more var declarations*
    origNums[0] = n;
    nums[0] = rightVal;
    *rest of the code*
}

I tried smaller mod values and they work perfectly fine, so it wasn't until I tried larger mods that this error came about, how can I fix this error?

  • 3
    Why are you passing an array size as a double? That is asking for trouble. – Brian61354270 Feb 13 '23 at 02:59
  • 7
    You're trying to allocate a 1.26 petabyte array. That allocation fails, so malloc returns a null pointer. You're then trying to write to that null pointer (0x00000000). – Brian61354270 Feb 13 '23 at 02:59
  • 1
    We don't cast the `void *` from malloc in C. – Allan Wind Feb 13 '23 at 04:03
  • What is an "inverse of a number? 1/a % n? Is mod even defined for floating point values? – Allan Wind Feb 13 '23 at 04:05
  • @Brian, Code might not be trying to allocate a 1.26 petabyte array if `size_t` is 32 -bit and `(n) * sizeof(double)` truncated. – chux - Reinstate Monica Feb 13 '23 at 05:39
  • @Miguel Rodriguez, " tried smaller mod values and they work perfectly fine, so it wasn't until I tried larger mods that this error came about" What were those values - exactly? – chux - Reinstate Monica Feb 13 '23 at 05:51
  • @Brian how would I go about allocating all of the powers of a^i 0 <= i < sqrt(177408180034551.0) or any such large quantity then? even if they were all integers the array would still be inmense compared to my memory so is there any way even that I can store all these values? shanksBSGS(6.0, 56186.0, 65537.0); works (this method in the original question simply provides a^-1 for the shanks BSGS algorithm), but this large value doesnt work for Shanks baby step giant step, so should I simply recalculate ba^-rk every single time and compare to my stored powers of a? – Miguel Rodriguez Feb 13 '23 at 10:17
  • @MiguelRodriguez `sqrt(177408180034551.0) --> ~13,319,466.2068...` "allocating all of the powers of `a^i 0 <= i < ~13,319,466.2068...` then `unsigned n = 13319467; double *p = malloc(sizeof p[0] * n); if (a==0) exit(-1); p[0] = a; for (unsigned i = 1; i – chux - Reinstate Monica Feb 13 '23 at 13:52
  • I forgot to mention they are all the powers (mod 177408180034551), so all of the powers are within the double range, although nowhere close to the integer range which is why I used double to begin with – Miguel Rodriguez Feb 13 '23 at 19:17

1 Answers1

2

how can I fix this error?

Code has at least these troubles:

Detect allocation failures

Also (double*) cast in not needed and better to size to the referenced object than type.

if (n > SIZE_MAX/sizeof(double)) {
  fprintf(stderr, "Request too large\n");
  exit(EXIT_FAILURE);
} 
double* nums = malloc(sizeof nums[0] * n);
if (nums == NULL) {
  fprintf(stderr, "Out of memory\n");
  exit(EXIT_FAILURE);
} 
double* origNums = malloc(sizeof origNums[0] * n);
if (origNums == NULL) {
  fprintf(stderr, "Out of memory\n");
  exit(EXIT_FAILURE);
} 

Tip: Enable all compiler warnings

Avoid floating point sizes

Use size_t. It is the right size, type and width needed for allocation sizing.

// double inverseModN(double a, double n)
double inverseModN(double a, size_t n)

... would give the same access violation
why is there no warning for nums[0] = rightVal;

C does not require runtime code to report access violation. Instead check the return value of malloc() against NULL and validity of passing 177408180034551.0 to malloc().

Try sizes far less than n = 177408180034551.0 and work your way up. Suggest 1000, 1000000, 1000000000, ...

OP's code may simply overflow (n) * sizeof(double) passed to a size_t parameter and so allocating 7C68 DFB8 bytes. Small enough to successfully allocate, yet too small for OP's need.

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256