2013-04-11 10 views
13

Dieses Programm soll die letzten 100 Ziffern einer beliebigen Fakultät geben. Mit dem counter2 ++ in main() passiert jedoch etwas Seltsames. counter2 wird für jedes Mal um +1 erhöht, wenn die Schleife in der main() -Funktion ausgeführt wird (was 99 mal der Fall ist). Dies ist jedoch, was angezeigt wird:Increment arbeiten sehr seltsam

2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 
46 
47 
48 
49 
50 
51 
52 
53 
54 
55 
56 
57 
58 
59 
60 
61 
62 
63 
64 
65 
66 
67 
68 
69 
71 
86 
90 
123 
164 
196 
207 
254 
300 
362 
432 
471 
551 
620 
630 
708 
761 
772 
857 
896 
985 
1036 
1100 
1116 
1207 
1209 
1280 
1356 
1417 
1452 
1512 

Counter2 endet als 1512 anstelle von 100, aber wenn ich entfernen entweder mult (i) oder tragen() von main(), dann zeigt es 100. Warum Zähler2 am Ende 1512 sein und nicht 100?

#include <iostream> 

using namespace std; 

int numbers[100]; 
int counter2 = 0; 

void init(){ 
//sets elements 1-99 of numbers[] to 0, increments counter2 by 1, sets numbers[0] = 1 
    for (int i = 1; i < 100; i++){ 
     numbers[i] = 0; 
    } 
    numbers[0] = 1; 
    counter2++; 
} 

void mult(int x){ 
//multiplies each element by 1 through n to calculate for !n 
//this is used to represent a very large number without using a BigInt library 
//the nth element is a placeholder for the n+1 position of the number 
//e.g 2nd element represents 100-900 of the number, 4th represents 1000-9000, etc 
//carry() is used to take care of overflow, so that it's only 1 digit per element 
    for (int i = 0; i < 100; i++){ 
     numbers[i] *= x; 
    } 
} 

void carry(){ 
//in order to make previous function work, this adds any overflow to the next 
//element. e.g: 8 * 4 = 32, 3 is added to numbers[i+1], sets numbers[i] to 2 
    int counter = 0; 
    for (int i = 0; i < 100; i++){ 
     if (numbers[i] >= 10){ 
      counter = numbers[i]/10; 
      numbers[i+1] += counter; 
      numbers[i] = numbers[i] % (counter * 10); 
     } 
    } 
} 

int main() 
{ 
    init(); 
    for (int i = 2; i < 101; i++){ 
    //calculates the last 100 digits of !100, but counter2 ends up being 1512 
     mult(i); 
     carry(); 
     counter2++; 
     cout << counter2 << endl; 
    } 
} 
+0

Was ist Ihre Frage? – Raptor

+0

Entschuldigung, warum ist counter2 = 1512? Warum wächst es merkwürdig? – xyz

+0

Es gibt keine andere Ausgabe, es hat mit Speicher zu tun, wie andere sagen. – xyz

Antwort

14

Sie schreiben über das Ende des numbers Array in carry():

 numbers[i+1] += counter; 

Hier i kann 99 sein, in welchem ​​Fall numbers[i+1] außerhalb der Grenzen ist.

Technisch ist dies undefined behaviour. In der Praxis passiert es, dass Sie die Variable count2 überschreiben, die sich direkt nach dem Array im Speicher befindet.

Eine unangenehme Sache über Gedächtnisfehler ist, dass sie für eine lange Zeit symptomlos gehen können, und dann in den schlimmsten möglichen Umständen auftauchen. valgrind ist ein großartiges Werkzeug zur Erkennung von Problemen dieses Typs.

+0

Warum wirkt sich das auf counter2 obwohl? – xyz

+0

Auch in 'mult', das von' main' aufgerufen wird, wenn 'i' 100 ist. –

+4

@Seb' counter2' ist möglicherweise neben dem Array im Speicher, so dass ein Write außerhalb des Arrays 'counter2' schreiben kann. –

2

In dieser Zeile

numbers[i+1] += counter; 

Sie also außerhalb der Grenzen des Arrays schreiben numbers[100];
wenn i == 99 den Wert int counter2 = 0; ändern, die (in Ihrem Fall, aber nicht notwendigerweise) liegt direkt neben Zahlen im Speicher.