C exe on winXP memory limitation

F

fermineutron

I wrote a program to calculate factorials of large numbers. The long
precission integers are stores in arrays. When i specify the length of
these arrays larger than 16000 elements, each element is a long int,
the windows refuses to execute the program. More precicely the code
terminates as soon as it starts to execute. How can i overcome this
issue. Note, if array length is set smaller the code runs with no
problems.

Here is the code:
==========================Start Paste==========================

#include<stdio.h>
#include<stdlib.h>
#include<math.h>

#define al 8024*8
#define base 1000
typedef long int IntegerArrayType;

struct AEI{
IntegerArrayType data[al];
long int digits;
};

void pack(IntegerArrayType i, struct AEI *N1);
void Aadd(struct AEI * A, struct AEI * B, struct AEI * C);
void Ambi(struct AEI * A, IntegerArrayType B, struct AEI * C);
void Lshift(struct AEI * A, IntegerArrayType B, struct AEI * C);
void Amult(struct AEI * A, struct AEI * B, struct AEI * C);
void AEIprintf(struct AEI * N1);
void AEIfprintf(FILE * fp, struct AEI * N1);


int main(void)
{

struct AEI N1, MO;
long i = 0, j = 0, ii, NUM;
FILE *ff;

while (i < al)
{
N1.data = 0;
MO.data = 0;
i++;
}

printf("Enter integer to Factorialize: ");
scanf("%ld", &NUM);

pack(1, &N1);
ff = fopen("Results.txt", "w");
printf("you entered: %ld", NUM);

i=1;
while(i < NUM )
{
ii = 1;

while (ii < al)
{
MO.data[ii] = 0;
ii++;
}

pack((i+1), &MO);

Amult(&N1, &MO, &N1);

printf("\nPogress: %d", i);

i++;

}
if(ff!=NULL){
fprintf(ff,"\n%d\n",i+1);
AEIfprintf(ff, &N1);
}
fclose(ff);

printf("\nPogress: 100%");

return 0;
}


void AEIprintf(struct AEI *N1){

double fieldLength;
double temp;
char format0[8];
char format1[8];
long j;
j = N1->digits-1;
fieldLength = log10(base);
temp = modf(fieldLength, &fieldLength);

format0[0] = '%';
format0[1] = fieldLength + 48;
format0[2] = 'd';
format0[3] = 0x00;
format1[0] = '%';
format1[1] = '0';
format1[2] = fieldLength + 48;
format1[3] = 'd';
format1[4] = 0x00;

printf(format0, N1->data[j]);
j--;

while (j >= 0)
{
printf(format1, N1->data[j]);

j--;
}

return;
}


void AEIfprintf(FILE * fp, struct AEI *N1){
long j = N1->digits-1;

double fieldLength, temp;
char format0[8], format1[8];

fieldLength = log10(base);
temp = modf(fieldLength, &fieldLength);

format0[0] = '%';
format0[1] = fieldLength + 48;
format0[2] = 'd';
format0[3] = 0x00;
format1[0] = '%';
format1[1] = '0';
format1[2] = fieldLength + 48;
format1[3] = 'd';
format1[4] = 0x00;

fprintf(fp,format0, N1->data[j]);
j--;

while (j >= 0){
fprintf(fp, format1, N1->data[j]);
j--;
}


return;
}



void pack(IntegerArrayType i, struct AEI * N1)
{
long t = 1, i1, j = 0;

while (t == 1){
i1 = i % base;
N1->data[j] = i1;
i = (i - i1) / base;
j++;
if (i == 0)
t = 0;
}
N1->digits=j;
return;
}

void Aadd(struct AEI *A, struct AEI *B, struct AEI *C){ /* C = A + B
*/
long carry = 0, result, i =0, d;
if(A->digits>B->digits){
d=A->digits;
}else{
d=B->digits;
}
while (i < d && i<al){
result = A->data + B->data + carry;
C->data = result % base;
carry = (result - result % base) / base;
i++;
}
if(carry!=0 && i<al){
C->data=carry;
d++;
}
if(i==al){
printf("\nAadd Array overflow");
}
C->digits=d;
return;

}

void Ambi(struct AEI *A, IntegerArrayType B, struct AEI *C){
/*C = A * B; B is integer; */
long carry = 0, result, i = 0, d;

d=A->digits;

while (i < d){
result = A->data * B + carry;
C->data = result % base;
carry = (result - result % base) / base;
i++;
}
if(carry!=0 && i<al){
C->data=carry;
d++;
}
if(i==al){
printf("\nAmbi Array overflow");
}
C->digits=d;
return;
}

void Lshift(struct AEI * A, IntegerArrayType B, struct AEI * C){
/*C = A LS B; B is integer; */
long i = 0;

while (i<A->digits && (i + B) < al){
C->data[i + B] = A->data;
i++;
}
if(i+B==al){
printf("\nArray overflow");
}
C->digits=A->digits+B;
return;
}

void Amult(struct AEI * A, struct AEI * B, struct AEI * C){
/*C = A * B; */
long i, ii;

struct AEI Temp, Temp1, ANS;

ii = 0;
while (ii < al){
ANS.data[ii] = 0;
ii++;
}
ANS.digits=0;
i = 0;
while (i < B->digits){

ii = 0;
while (ii < al){
Temp1.data[ii] = 0;
Temp.data[ii] = 0;
ii++;
}
Temp.digits=0;
Temp1.digits=0;
Lshift(A, i, &Temp);
if(B->data!=0){
Ambi(&Temp, B->data, &Temp1);
Aadd(&Temp1, &ANS, &ANS);
}
i++;

}
i = 0;
while(i<al){
C->data=ANS.data;
i++;
}
C->digits=ANS.digits;

return;
}

=========================End Paste=============================

thanks ahead.
 
F

fermineutron

By the way i am on emachine M6810 notebook with AMD Athlon64 3200 CPU
and 512 MB of ram. when i execute the code i have about 300MB of free
ram.
 
A

Ancient_Hacker

your problem as nothing to do with the C standard AFAIK.

But for future reference, any problem that shows up near a power of two
(I suspect the actual place it fails is nearer to 16,384) is likely to
be related to some limit, like a limit of 32,767 or 65,536 bytes per
local variable.

Try compiling your program with a 32-bit compiler and I suspect the
problem will go away, (or at least be postponed until the 32-bit limit).
 
F

fermineutron

Compied with lcc-win32,

if al is changeed to

#define al 8024*8

instead of what i had in earlier post, the program fails as it did with
BCpp5.02 compiler.
 
T

T.M. Sommers

fermineutron said:
I wrote a program to calculate factorials of large numbers. The long
precission integers are stores in arrays. When i specify the length of
these arrays larger than 16000 elements, each element is a long int,
the windows refuses to execute the program. More precicely the code
terminates as soon as it starts to execute. How can i overcome this
issue. Note, if array length is set smaller the code runs with no
problems.

Allocate your arrays dynamically.
Here is the code:
==========================Start Paste==========================

#include<stdio.h>
#include<stdlib.h>
#include<math.h>

#define al 8024*8
#define base 1000

Conventionally, #defines are given names in all capital letters,
and variables are not given names with all capital letters. This
is only a convention, but following it does make it easier for
others to read your code.
ff = fopen("Results.txt", "w");

You need to check that fopen worked.
printf("you entered: %ld", NUM);

You consistently fail to end output lines with newlines. That is
a bad habit, gains you nothing, and may lose output.
printf("\nPogress: %d", i);

i is a long, so use %ld. Spell 'progress' with an 'r'.
printf("\nPogress: 100%");

The '%' needs to be escaped.
char format0[8];

format0[0] = '%';
format0[1] = fieldLength + 48;
format0[2] = 'd';
format0[3] = 0x00;
printf(format0, N1->data[j]);

Easier to do this:

printf("%*d", fieldLength, N1->data[j]);
 
J

jacob navia

fermineutron said:
Compied with lcc-win32,

if al is changeed to

#define al 8024*8

instead of what i had in earlier post, the program fails as it did with
BCpp5.02 compiler.

I compiled with lcc-win32 with
#define al 8024*8 and it works.

lcc-win32 gives you 1MB stack.

jacob
 
F

fermineutron

I compiled with lcc-win32 with
#define al 8024*8 and it works.

lcc-win32 gives you 1MB stack.

jacob

Theoretically stack size should not matter in this case, since all
arguments are passed by reference.

Did you run it on windows?

I would not be surprized if its the evil windows that is at fault.
 
C

Coos Haak

Op 27 Oct 2006 10:10:07 -0700 schreef fermineutron:
Theoretically stack size should not matter in this case, since all
arguments are passed by reference.

Did you run it on windows?

What is the name of the compiler, would it be per chance be lcc-WIN32?
I would not be surprized if its the evil windows that is at fault.
Jacob writes the lcc-win32 compiler, would he not know?
 
B

Bill Medland

fermineutron said:
I wrote a program to calculate factorials of large numbers. The long
precission integers are stores in arrays. When i specify the length of
these arrays larger than 16000 elements, each element is a long int,
the windows refuses to execute the program. More precicely the code
terminates as soon as it starts to execute. How can i overcome this
issue. Note, if array length is set smaller the code runs with no
problems.

Here is the code:
==========================Start Paste==========================

#include<stdio.h>
#include<stdlib.h>
#include<math.h>

#define al 8024*8
#define base 1000
typedef long int IntegerArrayType;

struct AEI{
IntegerArrayType data[al];
long int digits;
};

Over 500000 bytes

snip
int main(void)
{

struct AEI N1, MO;
long i = 0, j = 0, ii, NUM;
FILE *ff;

while (i < al)
{
N1.data = 0;
MO.data = 0;
i++;
}

printf("Enter integer to Factorialize: ");
scanf("%ld", &NUM);

pack(1, &N1);
ff = fopen("Results.txt", "w");
printf("you entered: %ld", NUM);

i=1;
while(i < NUM )
{
ii = 1;

while (ii < al)
{
MO.data[ii] = 0;
ii++;
}

pack((i+1), &MO);

Amult(&N1, &MO, &N1);


VC++ ide debug shows stack overflow here

snip
void Amult(struct AEI * A, struct AEI * B, struct AEI * C){
/*C = A * B; */
long i, ii;

struct AEI Temp, Temp1, ANS;

1540632 bytes. A bit big for Microsoft's standard stack space (default is
probably only 1MB)

snip
=========================End Paste=============================

thanks ahead.

Allocate more stack space.
 
F

fermineutron

Allocate more stack space.

But all functions are called with pointers to structures, hence there
is very little stape on stack is used, plus the pointer size is
independent of size of structure that the pointer points to.
 
R

Richard Heathfield

fermineutron said:
I wrote a program to calculate factorials of large numbers. The long
precission integers are stores in arrays. When i specify the length of
these arrays larger than 16000 elements, each element is a long int,
the windows refuses to execute the program.

No C90 implementation is obliged to support objects larger than 32767 bytes.
No C99 implementation is obliged to support objects larger than 65535
bytes.

To determine whether you can get a larger object without crashing the
program if you can't, the best way is to get the space via malloc.

Your code has some problems which gcc diagnoses (see elsethread where
someone has already dealt with these), and some which it doesn't. I'm
reluctant to waste time pointing these out, since your track record in
fixing bugs is not good.
 
K

Kenneth Brody

fermineutron said:
But all functions are called with pointers to structures, hence there
is very little stape on stack is used, plus the pointer size is
independent of size of structure that the pointer points to.

Read it again. From your OP:
#define al 8024*8
#define base 1000
typedef long int IntegerArrayType;

struct AEI{
IntegerArrayType data[al];
long int digits;
}; [...]
int main(void)
{
struct AEI N1, MO;

There are no pointers used here. main() itself declares nearly 1MB
worth of local variables.

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
F

Flash Gordon

fermineutron said:
Theoretically stack size should not matter in this case, since all
arguments are passed by reference.

However, the variable is at some point declared and therefore needs
space. You declared the variable as local to main and therefore it is
quite likely that a compiler will put it on the stack.
Did you run it on windows?

Note the -win32 that is part of the name of the compiler.
I would not be surprized if its the evil windows that is at fault.

Not as such. If you want to know the whys and wherefore of the specifics
of Windows and lcc-win32 than I'm sure Jacob will be happy to discus
them with you, as the autor of lcc-win32 he probably knows a bit about
the subject. However, discussion of the details of it would not be
topical here (comp.compilers.lcc or one of the Windows groups would be a
good place), all we can say here is that *all* implementations in this
universe have limits and what you are trying to do greatly exceeds the
minimum any implementation is required to support.
 
B

Bart

fermineutron said:
But all functions are called with pointers to structures, hence there
is very little stape on stack is used,

Really? Then what's this?
int main(void)
{
struct AEI N1, MO;

Looks like two structures created on the stack. But wait! There's more:
void Amult(struct AEI * A, struct AEI * B, struct AEI * C){
/*C = A * B; */
long i, ii;
struct AEI Temp, Temp1, ANS;

Looks like three more structures created on the stack.

Well, that's already five structures. Let's see what's the size of the
structure:
#define al 8024*8
#define base 1000
typedef long int IntegerArrayType;

struct AEI{
IntegerArrayType data[al];
long int digits;
};

According to the above, the structure has to be at least 256772 bytes,
which means you have over 1.2 megabytes on the stack.

Regards,
Bart.
 
F

fermineutron

I did not realize that defining objects uses the stack, i thought that
it uses additional memory, while the stack is only used for passing
args to functions.

In asembly stack segment is separate from data segment.

I guess its not the same in C.
 
B

Bart

fermineutron said:
I did not realize that defining objects uses the stack, i thought that
it uses additional memory, while the stack is only used for passing
args to functions.

In asembly stack segment is separate from data segment.

Even in assembly you would allocate "automatic" objects on the stack.
I guess its not the same in C.

C doesn't even have to have a stack.

Regards,
Bart.
 
F

fermineutron

Ok, i want to figure this out:

According to Kip R Irvine "Assembly Language for intel dased computers"

An executable file has to have 3 Segments, (Notice capitol S)
data Segment
code Segment
stack Segment

Furthermore depending on the .model directive, the Segments could be
equal to or greater than 1 segment (notice low case s)

now segment is a chunk of RAM equal to 64KB or less, this way offset is
a 16-bit addreess within a segment and direct memory address is
segment:eek:ffset = 32 bits.

So, when compiler translates the C code into asm, does it create the
data Segment, to store variables which are declared in functions?
From the coments herein it seems logical to conclude that C compiler
does not create the .data Segment at all?

Am I missing something?
 
B

Bart

fermineutron said:
Am I missing something?

You're quite confused with C as well as Intel assembly language. But
there's no point writing any kind of explanation because you never read
past the first two sentences. Then, thinking you understand everything
you go on and write heaps of totally misguided and incorrect code. I
bet that's how you read your C and assembly books too.

Learning to program takes patience and care. Your approach is never
going to get you anywhere.

Regards,
Bart.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top