0

(edited to correct a mistake and specify code is written for C++)

I am making a large array, P_arr of size

    int N = 30;
    float P_arr[27000][4];

with elements given by

    float ua_min = 0.0001, ua_max = 0.0075, us_min = 2, us_max = 100, g_min = 0.1, g_max = 0.8;

    float ua_start = ua_min + ua_min;
    float ua_end = ua_max - ua_max;
    float us_start = us_min + us_min;
    float us_end = us_max - us_max; 
    float g_start = g_min + g_min; 
    float g_end = g_max - g_max;

    float ua_stepSize = (ua_end - ua_start) / (N - 1);
    float us_stepSize = (us_end - us_start) / (N - 1);
    float g_stepSize = (g_end - g_start) / (N - 1);

    float ua_arr[3];
    float us_arr[3];
    float g_arr[3];

    ua_arr[0] = ua_start;
    us_arr[0] = us_start;
    g_arr[0] = g_start;

    for (int j = 1; j < N; j++)
    {
        ua_arr[j] = ua_arr[j - 1] + ua_stepSize;
        us_arr[j] = us_arr[j - 1] + us_stepSize;
        g_arr[j] = g_arr[j - 1] + g_stepSize;
    }

    int i = 0;
    for (int u = 0; u < N; u++)
    {
        for (int w = 0; w < N; w++)
        {
            for (int v = 0; v < N; v++)
            {
                P_arr[i][2] = g_arr[v];
                P_arr[i][1] = us_arr[w];
                P_arr[i][0] = ua_arr[u];
                i++;
            }
        }
    }

such that the number of rows is always N ^ 3.

Once I increase N > ~ 30, and I increase the size of P_arr accordingly, the code fails to write the P_arr and "exits with code: -1073741571."

Is there a length limit to the array I construct? How can I get around this to define larger arrays, say with N = 100?

update

float(*P_arr)[4] = new float[42875][4]; seems to increase the limit of N -> ~ 35 and row limit to N^3 = 42875. Is my dynamic allocation incorrect as it is imposing this limit?

Zachary
  • 5
  • 3
  • 1
    Is this an automatic array? Stack frames have limited size, so you can't allocate very large local arrays. Make it static. – Barmar Aug 17 '23 at 15:33
  • 1
    From the code snippets we cannot see if the array has storage class `auto` which may lead to a stack overflow. Please [edit] your question and show the complete code in a single code block to allow us to copy&paste and compile it, i.e. a [mre]. – Bodo Aug 17 '23 at 15:34
  • When you change `N`, do you change the size of `p_arr`? – Eric Postpischil Aug 17 '23 at 16:01
  • @Barmar - I did think P_arr was static. Am I incorrect? – Zachary Aug 17 '23 at 16:17
  • @Bodo - I've added the rest of the code. – Zachary Aug 17 '23 at 16:21
  • @EricPostpischil - the question was edited for clarity. the number of rows is always changed to match N^3. – Zachary Aug 17 '23 at 16:22
  • Instead of using a 2d array, prefer to use `std::vector` of a struct/class. The struct will help ensure that the data for rows is on the same data cache line, avoiding cache reloads. – Thomas Matthews Aug 17 '23 at 17:22
  • @Zachary It depends on where the declaration is located. If it's inside a function, it's local and automatic; if it's outside a function it's static. You can make a local variable static by adding the `static` qualifier to the declaration. – Barmar Aug 17 '23 at 18:14
  • @Barmar - and adding static qualifier increases its limiting size? Adding static float(*P_arr)[4] = new float[42875][4]; doesn't seem to change the result. – Zachary Aug 17 '23 at 18:17
  • Yes, then it's stored in the same memory used for global variables, which is almost unlimited. – Barmar Aug 17 '23 at 18:19
  • @Barmar - Okay, I will look into this, but unfortunately it doesn't seem to change the result in this case. – Zachary Aug 17 '23 at 18:24
  • Your code is still incomplete as there is no `main` function, and it shows statements that must be in a function. It is still not clear if your definition of `float P_arr[27000][4];` is inside a function or not. – Bodo Aug 17 '23 at 19:11

6 Answers6

1

In the C programming language, the maximum number of rows allowed for an array is determined by several factors, including the available memory and the specific platform or environment in which your program is running. C arrays are typically allocated on the stack or the heap, and the available memory for these allocations can vary.

On the stack, the maximum size of an array can be limited by the stack size, which is usually smaller than the heap size. Stack size is often limited to a few megabytes, and if you try to allocate an array that's too large, you might encounter a stack overflow.

On the heap, the maximum size of an array can be constrained by the available system memory. However, the heap generally allows for larger allocations than the stack. Still, trying to allocate a massive array on the heap might lead to memory allocation failures if the system doesn't have enough available memory.

It's important to note that exceeding the available memory, whether on the stack or the heap, can lead to program crashes, data corruption, or other unexpected behavior.

In practice, if you need to work with very large arrays, you might want to consider dynamic memory allocation using functions like malloc() and free(), which allow you to allocate memory on the heap as needed. This approach gives you more control over memory usage and can help you avoid some of the limitations associated with stack-based arrays.

Remember that the specific limitations can vary based on the compiler, platform, and system configuration you're using. It's always a good idea to be aware of the memory constraints of your target environment when working with arrays in C.

chamanswami
  • 37
  • 1
  • 3
0

Once I increase N > ~ 30, the code fails

As i increments N*N*N times. float P_arr[27000][4]; is only large enough for N up to 30.

For N > 30, use a larger P_arr[],

#define SZ 100
int N = SZ;
float P_arr[SZ*SZ*SZ][4];
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

When you need large arrays - place them on the heap. Use pointers to array to simplify the access.

Example:

float (*large2DArray)[200000];
large2DArray = malloc(100000*sizeof(*large2DArray);


for(size_t row = 0; row < 100000; row++)
    for(size_t col = 0; col < 200000; col++)
        large2DArray[row][col] = (float)rand() / rand(); 
0___________
  • 60,014
  • 4
  • 34
  • 74
  • I am trying to apply this dynamic allocation method. When I try your code I have the error: "value of type "void*" cannot be assigned to an entity of type "float (*)" – Zachary Aug 17 '23 at 16:34
  • @Zachary it meand that you compile C code using C++ compiler – 0___________ Aug 17 '23 at 20:24
0

Arrays with automatic storage duration (any array defined inside a function without using static or _Thread_local) are usually implemented using a hardware stack. The default stack sizes are 8 MiB on macOS, 2 MiB on Linux, and 1 MiB on Microsoft Windows.1 Thus, your code overruns the space set for the stack, and the program crashes.

Generally, when you need a large array, you should allocate space for it using malloc or a related routine:

float (*P_arr)[4] = malloc(N * N * N * sizeof *P_arr);
if (!P_arr)
{
    fprintf(stderr, "Error, unable allocate memory for P_arr in line %d.\n", __LINE__);
    exit(EXIT_FAILURE);
}

… // Work with P_arr.

free(P_arr); 

Footnote

1 “MiB” stands for Mebibyte, 220 bytes = 1,048,576 bytes.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • Okay, however when I try this I have the same issue as in an answer below: I have the error: "value of type "void*" cannot be assigned to an entity of type "float (*)" – Zachary Aug 17 '23 at 16:42
  • @Zachary: That is a C++ error message, so it indicates you are compiling using C++, not C. – Eric Postpischil Aug 17 '23 at 16:45
  • This is my mistake. I am using a C++ compiler and mean to write the code in C++. I will update the question. – Zachary Aug 17 '23 at 17:02
0

To answer your question, the maximum index is the maximum value for a size_t type.

The "maximum size" of an array is restricted by your system's memory limitations. This depends on where you put the array.

Array on Stack

The stack or local variable area, traditionally has a smaller amount of memory allocated. The idea is that only parameters, small quanities of local variables and return addresses are stored on the stack. This is usually a small set of stuff.

Array on Heap

Build systems and the OS grant a program more dynamic memory area, a.k.a. heap. Some designs are that the heap grows towards the stack. Be careful here because an OS may have to swap out your program with another program, and that includes the memory area.

Array on Static / Automatic / Global

There is another area that doesn't get much discussion, which is the static / automatic / global memory area. For example, a static variable inside a function gets placed in this area, as well as global variables. This area may be larger than the heap or smaller, depending on the build system and the operating system.

Array on Operating System memory

Many operating systems have API to allocate memory and different types of memory. You will need to look up the maximum capacity. One maximum may be the RAM limit of your system. Another would be the size of your hard drive (the OS may use virtual memory and swap to the hard drive).

Array on Memory Mapped

Some operating systems support allocating memory directly on a file. The operating system will manage the swapping from RAM to file for you. The size limit for this is closer to the available space on your hard drive.

Is the size necessary?

In the ancient days, most computers had very little memory. Data processing and storage used tape drives, since more data could be stored in a file than in system memory. Array processing was performed in smaller blocks or chunks. Temporary files were create as necessary to hold interim results.

Do you really need to hold all that data in memory at once?
Can you break it up into smaller pieces? Smaller pieces are easier for today's processors. Align your data with the size of your processor's data cache or the loading page size. No need to have data around that you are not using.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
-3

Consider the following:

#include <limits.h>
#include <stdio.h>

int main(void)
{
    printf("INT_MIN: %d\n", INT_MIN);
    printf("INT_MAX: %d\n", INT_MAX);
    return 0;
}

On my machine I get:

$ gcc main.c; ./a.out;
INT_MIN: -2147483648
INT_MAX: 2147483647

As you can see -2147483648 == -2^31 and 2147483647 == (2^31 - 1).

To increase your range you can use long int:

#include <limits.h>
#include <stdio.h>

int main(void)
{
    printf("LONG_MIN: %ld\n", LONG_MIN);
    printf("LONG_MAX: %ld\n", LONG_MAX);
    return 0;
}

My output is:

$ gcc main.c; ./a.out;
LONG_MIN: -9223372036854775808
LONG_MAX: 9223372036854775807

To explicitly set the bit width you can use int32_t, int64_t (and possibly __int128_t, in stdint.h.

Fiddling Bits
  • 8,712
  • 3
  • 28
  • 46