Visual C++ Array Size Crash [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Stack overflow visual C++, potentially array size?
This code is simply meant to read values from a binary file into the array DataBuffer. When the size of DataBuffer is greater than or equal to 515000, it simply crashes. I am developing this in Visual C++ 2010 on Windows 7. The function cbFileRead() is something whose source code I can not access. cbFileRead() expects DataBuffer to be of the type USHORT*.
#include <stdio.h> // printf()
#include "cbw.h" // cbFileRead()
int main(int argc, char* argv[]) {
// Declarations
char* FileName = argv[1];
long FirstPoint = 0;
long NumPoints;
// Set data collection sizes
const long chunkSize = 515000;
NumPoints = chunkSize; // Number of points to be read into mem
WORD DataBuffer[chunkSize-1];
// Get data
cbFileRead(FileName, FirstPoint, &NumPoints, DataBuffer);
printf("Completed on data point %d whose value is %d\n", NumPoints, DataBuffer[chunkSize-1]);
return 0;
}
What reasons are there for this crashing? I would expect the array size to be able to go much higher.

The printf() is going beyond the end of the array DataBuffer, as it has chunksize - 1 elements so the last element is chunksize - 1 - 1. The function cbFileRead() is (possibly) misinformed of the number of elements in DataBuffer also.
EDIT:
As others have already stated, the default stack size is 1MB. The size of the DataBuffer array is 2 * 515000 which equals 1030000, which leaves 18576 free bytes on the stack. cbFileRead() could easily be declaring a large buffer on the stack for reading from file. As suggested by everyone else, allocate the DataBuffer on the heap using new[] (and delete[] to free) or use vector<WORD>.

The default stack reservation size used by the linker is 1 MB. To
specify a different default stack reservation size for all threads and
fibers, use the STACKSIZE statement in the module definition (.def)
file.
Microsoft Dev Center - Thread Stack Size
Or you can allocate the memory dynamically with the new keyword.

Your stack size may not be large enough to handle local data of that size (assuming this is what you mean by "crash"):
// use dynamic allocation instead of stack local
WORD *DataBuffer = new WORD[chunkSize];
cbFileRead(FileName, FirstPoint, &NumPoints, DataBuffer);
// ...use DataBuffer...
// deallocate DataBuffer when done
delete[] DataBuffer;

On most platforms, including Windows, local variables are stored on a stack, which has a limited size - in this case, it looks like it's around 1MB. There's probably a way to increase that size if you really need to, but it would be better to allocate large arrays dynamically:
#include <vector>
std::vector<WORD> DataBuffer(chunkSize); // guessing that "chunkSize-1" was an error
cbFileRead(FileName, FirstPoint, &NumPoints, &DataBuffer[0]);
printf("Completed on data point %d whose value is %d\n",
NumPoints, DataBuffer[chunkSize-1]);
Note that, if the array size is actually supposed to be chunkSize-1, then the last element would be DataBuffer[chunkSize-2], since arrays are indexed from zero.

Related

Large arrays on local variables work on Linux but not on Windows [duplicate]

This question already has answers here:
Segmentation fault on large array sizes
(7 answers)
Closed 3 years ago.
Program with large global array:
int ar[2000000];
int main()
{
}
Program with large local array:
int main()
{
int ar[2000000];
}
When I declare an array with large size in the main function, the program crashes with "SIGSEGV (Segmentation fault)".
However, when I declare it as global, everything works fine. Why is that?
Declaring the array globally causes the compiler to include the space for the array in the data section of the compiled binary. In this case you have increased the binary size by 8 MB (2000000 * 4 bytes per int). However, this does mean that the memory is available at all times and does not need to be allocated on the stack or heap.
EDIT: #Blue Moon rightly points out that an uninitialized array will most likely be allocated in the bss data segment and may, in fact, take up no additional disk space. An initialized array will be allocated statically.
When you declare an array that large in your program you have probably exceeded the stack size of the program (and ironically caused a stack overflow).
A better way to allocate a large array dynamically is to use a pointer and allocate the memory on the heap like this:
using namespace std;
int main() {
int *ar;
ar = malloc(2000000 * sizeof(int));
if (ar != null) {
// Do something
free(ar);
}
return 0;
}
A good tutorial on the Memory Layout of C Programs can be found here.

Initiate array (size:20000001) inside main function throws SIGSEGV [duplicate]

This question already has answers here:
Segmentation fault on large array sizes
(7 answers)
Closed 3 years ago.
Program with large global array:
int ar[2000000];
int main()
{
}
Program with large local array:
int main()
{
int ar[2000000];
}
When I declare an array with large size in the main function, the program crashes with "SIGSEGV (Segmentation fault)".
However, when I declare it as global, everything works fine. Why is that?
Declaring the array globally causes the compiler to include the space for the array in the data section of the compiled binary. In this case you have increased the binary size by 8 MB (2000000 * 4 bytes per int). However, this does mean that the memory is available at all times and does not need to be allocated on the stack or heap.
EDIT: #Blue Moon rightly points out that an uninitialized array will most likely be allocated in the bss data segment and may, in fact, take up no additional disk space. An initialized array will be allocated statically.
When you declare an array that large in your program you have probably exceeded the stack size of the program (and ironically caused a stack overflow).
A better way to allocate a large array dynamically is to use a pointer and allocate the memory on the heap like this:
using namespace std;
int main() {
int *ar;
ar = malloc(2000000 * sizeof(int));
if (ar != null) {
// Do something
free(ar);
}
return 0;
}
A good tutorial on the Memory Layout of C Programs can be found here.

How to eleminate access voilation writing location

I am dealing with arrays of size ((128*75)*(128*75)) in C.Whenever I declared the array as global,there is no issue like
#include<stdio.h>
float buf[(128*75)*(128*75)]
int main()
{
//using buf in different functions works fine
}
But whenever i declared it using malloc and using in main() getting access violation writing location error,
#include<stdio.h>
int main()
{
float * buf;
buf = malloc((128*75)*(128*75));
//using buf in different functions gives error
}
What is the reason for it?
malloc(x) only reserves x bytes, not x floats.
The global arrays is indeed 128*75*128*75 floats in size. The malloc-ed buffer is only 128*75*128*75 bytes in size, i.e. can only contain one fourth of the required number of floats (assuming a float is 4 bytes on your platform).
That is why you probably access beyond the limits of the malloc-ed buffer and get a segfault/access violation or whatever it is called on your platform.
You can use calloc() or you can use a size of 128*75*128*75*sizeof(float) as argument to malloc().
first, why not do:
int size = 128*75*128*75;
float buf[size];
second, check buf != NULL before using it, because malloc may have failed (if malloc failed, you will get NULL as return value - so you may miss that, if the array you tried to use is too big - you'll get compilation error - can't miss)
third, use sizeof inside malloc: buf = malloc(sizeof(float)*size); (as said by others, malloc allocates bytes and when declaring array - the compiler knows the type of element you want, so it gives you array with that size - meaning int a[2] size is 2*sizeof(int) but malloc(2) size is 2 bytes which is smaller

C++ crash when accessing array of arrays [duplicate]

This question already has answers here:
Segmentation fault on large array sizes
(7 answers)
Closed 3 years ago.
Program with large global array:
int ar[2000000];
int main()
{
}
Program with large local array:
int main()
{
int ar[2000000];
}
When I declare an array with large size in the main function, the program crashes with "SIGSEGV (Segmentation fault)".
However, when I declare it as global, everything works fine. Why is that?
Declaring the array globally causes the compiler to include the space for the array in the data section of the compiled binary. In this case you have increased the binary size by 8 MB (2000000 * 4 bytes per int). However, this does mean that the memory is available at all times and does not need to be allocated on the stack or heap.
EDIT: #Blue Moon rightly points out that an uninitialized array will most likely be allocated in the bss data segment and may, in fact, take up no additional disk space. An initialized array will be allocated statically.
When you declare an array that large in your program you have probably exceeded the stack size of the program (and ironically caused a stack overflow).
A better way to allocate a large array dynamically is to use a pointer and allocate the memory on the heap like this:
using namespace std;
int main() {
int *ar;
ar = malloc(2000000 * sizeof(int));
if (ar != null) {
// Do something
free(ar);
}
return 0;
}
A good tutorial on the Memory Layout of C Programs can be found here.

What should I do to get the size of a 'dynamic' array? [duplicate]

This question already has answers here:
How do I find the length of an array?
(30 answers)
Closed 8 years ago.
I have this code.
int x[5];
printf("%d\n",sizeof(x) );
int *a;
a = new int[3];
printf("%d\n",sizeof(*a));
When I pass a 'static' array to sizeof(), it returns the dimension of the declared array multiplied by the number of bytes that the datatype uses in memory. However, a dynamic array seems to be different. My question is what should I do to get the size of an 'dynamic' array?
PD: Could it be related to the following?
int *a;
a=new int[3];
a[0]=3;
a[1]=4;
a[2]=5;
a[3]=6;
Why can I modify the third position if it's supposed I put a 'limit' in "a=new int[3]".
When I pass a 'static' array to sizeof(), it returns the dimension of the declared array multiplied by the number of bytes that the datatype uses in memory.
Correct, that is how the size of the entire array is computed.
However, a dynamic array seems to be different.
This is because you are not passing a dynamic array; you are passing a pointer. Pointer is a data type with the size independent of the size of the block of memory to which it may point, hence you always get a constant value. When you allocate memory for your dynamically sized memory block, you need to store the size of allocation for future reference:
size_t count = 123; // <<== You can compute this count dynamically
int *array = new int[count];
cout << "Array size: " << (sizeof(*array) * count) << endl;
C++14 will have variable-length arrays. These arrays will provide a proper size when you check sizeof.
Could it be related to the following? [...]
No, it is unrelated. Your code snippet shows undefined behavior (writing past the end of the allocated block of memory), meaning that your code is invalid. It could crash right away, lead to a crash later on, or exhibit other arbitrary behavior.
In C++ arrays do not have any intrinsic size at runtime.
At compile time one can use sizeof as you showed in order to obtain the size known to the compiler, but if the actual size is not known until runtime then it is the responsibility of the program to keep track of the length.
Two popular strategies are:
Keep a separate variable that contains the current length of the array.
Add an extra element to the end of the array that contains some sort of marker value that indicates that it's the last element. For example, if your array is known to be only of positive integers then you could use -1 as your marker.
If you do not keep track of the end of your array and you write beyond what you allocated then you risk overwriting other data stored adjacent to the array in memory, which could cause crashes or other undefined behavior.
Other languages tend to use the former strategy and provide a mechanism for obtaining the current record of the length. Some languages also allow the array to be dynamically resized after it's created, which usually involves creating a new array and copying over all of the data before destroying the original.
The vector type in the standard library provides an abstraction over arrays that can be more convenient when the size of the data is not known until runtime. It keeps track of the current array size, and allows the array to grow later. For example:
#include <vector>
int main() {
std::vector<int> a;
a.push_back(3);
a.push_back(4);
a.push_back(5);
a.push_back(6);
printf("%d\n", a.size());
return 0;
}
As a side-note, since a.size() (and sizeof(...)) returns a size_t, which isn't necessarily the same size as an int (though it happens to be on some platforms), using printf with %d is not portable. Instead, one can use iostream, which is also more idiomatic C++:
#include <iostream>
std::cout << a.size() << '\n';
You do not, at least not in standard C++. You have to keep track of it yourself, use an alternative to raw pointers such as std::vector that keeps track of the allocated size for you, or use a non-standard function such as _msize https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/msize?view=msvc-160 on Microsoft Windows or malloc_size https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/malloc_size.3.html on MacOS X.