Is there a max array length limit in C++?

后端 未结 12 1509
深忆病人
深忆病人 2020-11-22 07:21

Is there a max length for an array in C++?

Is it a C++ limit or does it depend on my machine? Is it tweakable? Does it depend on the type the array is made of?

相关标签:
12条回答
  • 2020-11-22 07:54

    There are two limits, both not enforced by C++ but rather by the hardware.

    The first limit (should never be reached) is set by the restrictions of the size type used to describe an index in the array (and the size thereof). It is given by the maximum value the system's std::size_t can take. This data type is large enough to contain the size in bytes of any object

    The other limit is a physical memory limit. The larger your objects in the array are, the sooner this limit is reached because memory is full. For example, a vector<int> of a given size n typically takes multiple times as much memory as an array of type vector<char> (minus a small constant value), since int is usually bigger than char. Therefore, a vector<char> may contain more items than a vector<int> before memory is full. The same counts for raw C-style arrays like int[] and char[].

    Additionally, this upper limit may be influenced by the type of allocator used to construct the vector because an allocator is free to manage memory any way it wants. A very odd but nontheless conceivable allocator could pool memory in such a way that identical instances of an object share resources. This way, you could insert a lot of identical objects into a container that would otherwise use up all the available memory.

    Apart from that, C++ doesn't enforce any limits.

    0 讨论(0)
  • 2020-11-22 07:55

    Nobody mentioned the limit on the size of the stack frame.

    There are two places memory can be allocated:

    • On the heap (dynamically allocated memory).
      The size limit here is a combination of available hardware and the OS's ability to simulate space by using other devices to temporarily store unused data (i.e. move pages to hard disk).
    • On the stack (Locally declared variables).
      The size limit here is compiler defined (with possible hardware limits). If you read the compiler documentation you can often tweak this size.

    Thus if you allocate an array dynamically (the limit is large and described in detail by other posts.

    int* a1 = new int[SIZE];  // SIZE limited only by OS/Hardware
    

    Alternatively if the array is allocated on the stack then you are limited by the size of the stack frame. N.B. vectors and other containers have a small presence in the stack but usually the bulk of the data will be on the heap.

    int a2[SIZE]; // SIZE limited by COMPILER to the size of the stack frame
    
    0 讨论(0)
  • 2020-11-22 07:57

    As annoyingly non-specific as all the current answers are, they're mostly right but with many caveats, not always mentioned. The gist is, you have two upper-limits, and only one of them is something actually defined, so YMMV:

    1. Compile-time limits

    Basically, what your compiler will allow. For Visual C++ 2017 on an x64 Windows 10 box, this is my max limit at compile-time before incurring the 2GB limit,

    unsigned __int64 max_ints[255999996]{0};
    

    If I did this instead,

    unsigned __int64 max_ints[255999997]{0};
    

    I'd get:

    Error C1126 automatic allocation exceeds 2G

    I'm not sure how 2G correllates to 255999996/7. I googled both numbers, and the only thing I could find that was possibly related was this *nix Q&A about a precision issue with dc. Either way, it doesn't appear to matter which type of int array you're trying to fill, just how many elements can be allocated.

    2. Run-time limits

    Your stack and heap have their own limitations. These limits are both values that change based on available system resources, as well as how "heavy" your app itself is. For example, with my current system resources, I can get this to run:

    int main()
    {
        int max_ints[257400]{ 0 };
        return 0;
    }
    

    But if I tweak it just a little bit...

    int main()
    {
        int max_ints[257500]{ 0 };
        return 0;
    }
    

    Bam! Stack overflow!

    Exception thrown at 0x00007FF7DC6B1B38 in memchk.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x000000AA8DE03000). Unhandled exception at 0x00007FF7DC6B1B38 in memchk.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x000000AA8DE03000).

    And just to detail the whole heaviness of your app point, this was good to go:

    int main()
    {
        int maxish_ints[257000]{ 0 };
        int more_ints[400]{ 0 };
        return 0;
    }  
    

    But this caused a stack overflow:

    int main()
    {
        int maxish_ints[257000]{ 0 };
        int more_ints[500]{ 0 };
        return 0;
    }  
    
    0 讨论(0)
  • 2020-11-22 07:58

    Looking at it from a practical rather than theoretical standpoint, on a 32 bit Windows system, the maximum total amount of memory available for a single process is 2 GB. You can break the limit by going to a 64 bit operating system with much more physical memory, but whether to do this or look for alternatives depends very much on your intended users and their budgets. You can also extend it somewhat using PAE.

    The type of the array is very important, as default structure alignment on many compilers is 8 bytes, which is very wasteful if memory usage is an issue. If you are using Visual C++ to target Windows, check out the #pragma pack directive as a way of overcoming this.

    Another thing to do is look at what in memory compression techniques might help you, such as sparse matrices, on the fly compression, etc... Again this is highly application dependent. If you edit your post to give some more information as to what is actually in your arrays, you might get more useful answers.

    Edit: Given a bit more information on your exact requirements, your storage needs appear to be between 7.6 GB and 76 GB uncompressed, which would require a rather expensive 64 bit box to store as an array in memory in C++. It raises the question why do you want to store the data in memory, where one presumes for speed of access, and to allow random access. The best way to store this data outside of an array is pretty much based on how you want to access it. If you need to access array members randomly, for most applications there tend to be ways of grouping clumps of data that tend to get accessed at the same time. For example, in large GIS and spatial databases, data often gets tiled by geographic area. In C++ programming terms you can override the [] array operator to fetch portions of your data from external storage as required.

    0 讨论(0)
  • 2020-11-22 07:59

    As has already been pointed out, array size is limited by your hardware and your OS (man ulimit). Your software though, may only be limited by your creativity. For example, can you store your "array" on disk? Do you really need long long ints? Do you really need a dense array? Do you even need an array at all?

    One simple solution would be to use 64 bit Linux. Even if you do not physically have enough ram for your array, the OS will allow you to allocate memory as if you do since the virtual memory available to your process is likely much larger than the physical memory. If you really need to access everything in the array, this amounts to storing it on disk. Depending on your access patterns, there may be more efficient ways of doing this (ie: using mmap(), or simply storing the data sequentially in a file (in which case 32 bit Linux would suffice)).

    0 讨论(0)
  • 2020-11-22 08:00

    i would go around this by making a 2d dynamic array:

    long long** a = new long long*[x];
    for (unsigned i = 0; i < x; i++) a[i] = new long long[y];
    

    more on this here https://stackoverflow.com/a/936702/3517001

    0 讨论(0)
提交回复
热议问题