Declaring a long long array with unsigned int size - c

I was doing a problem when I encountered a segmentation fault while declaring an array as:
long long ways[max+1];
where,
unsigned int max = findMax(l,T); // l is an unsigned int array and T is an int.
and findMax is a function of the type:
unsigned int findMax(unsigned int arr[],int size)
How can I resolve this?

A probable reason is that the array is too big for the stack.
Typical stack sizes as of now is 1-16 Mb (could be considerably less in an embedded system). If long long is 8 bytes it would mean that allocating one array of more than 125000 elements could be problematic. And you also want to leave room for other auto variables.
Really big arrays should not be allocated on the stack.
You could try allocating it in the heap instead:
long long *ways = calloc(max+1, sizeof *ways);
if (ways == NULL) {
// allocation failed!!
}
// Do stuff.
free(ways);

Related

Generation of array of size 10^6 in C

I am testing the sorting techniques (Mergesort, Quicksort,...so on) in 'C' experimentally for comparison of time. For this purpose, I am generating an array of large sizes up to 10^8 randomly as shown in the code below. But this piece of code is working for the generation of size up to 10^5. If this limit exceeds the compiler stops working and displays a dialogue box "a.exe has stopped working".
Please help me out with this problem.
Thanks
int main(){
srand(time(NULL));
long long int sz;
printf("Enter the size of array::");
scanf("%lld",&sz);
array_generate(sz);
}
long long int array_generate(long long int sz){
long long int randArray[sz];
long long int i;
for(i=0;i<sz;i++)
randArray[i]=rand()%1000; //Generate number between 0 to 1000
}
Your code is creating very large arrays as local variables. Locals typically reside on the stack which is limited in size, so by defining such a large local array you are overflowing the stack, causing your program to crash.
Use malloc instead to dynamically allocate memory on the heap which is much larger.
long long int *randArray = malloc(sz * sizeof *randArray);
As #dbush pointed out, you can't dynamically allocate such large arrays on the stack. You must use the heap instead.
As a general advise I would say never write something like that unless you really know what you're doing :
int array[dynamic_size];
Instead use a fixed size array like so :
#define FIXED_SIZE 200
[...]
int array[FIXED_SIZE];
// or int array[200];
Or use malloc (3).
Regarding your code, what is usually done in C is that the caller allocates memory and passes its pointer to the function initializing it. So your main would look like that :
int main(){
srand(time(NULL));
long long int sz;
printf("Enter the size of array::");
scanf("%lld",&sz);
// "sizeof *array" is the same as "sizeof(long long int)" but better because if you change the type of your array later, you won't have to change it twice (better from a maintainability POV)
long long int *array = malloc(sz * sizeof *array);
array_generate(array, sz);
array_process(array, sz);
free(array);
array = NULL; // not mandatory
}

C realloc not changing array

So, to start off I've already looked at a few questions including this one and none of them seem to help.
I'm simply trying to write a function that extends the size of an array using realloc().
My code currently looks like this:
unsigned char *xtnd = malloc(4);
xtndc(&xtnd, 4);
// sizeof(*xtnd) should now be 8
void xtndc ( unsigned char ** bytesRef , uint8_t count ) {
*bytesRef = realloc(*bytesRef, (sizeof(**bytesRef)) + count);
}
But no matter what I do it seems that the size of xtnd is always 4. After running xtndc() on it it should now be 8 bytes long.
Any suggestions?
The type of **bytesRef is unsigned char, so sizeof(**bytesRef) is 1. sizeof doesn't keep track of dynamic allocations, it's a compile time tool that gives you the size of a type, in this case unsigned char.
You have to keep track of the array size manually to calculate the new required size.
Your program does in fact change the size of the memory block. It changes the size of your original memory block from 4 bytes to 5 bytes. It changes to 5 bytes because you are essentially doing sizeof(unsigned char) + 4 which 1 + 4 = 5. If you want to double the size instead, do count*sizeof(unsigned char) + count. There are two points to be noted here:
The sizeof function returns the size of the data type, not the size of the allocated bytes. There is no way to know the size of the dynamically allocated memory.
The function realloc (and malloc and calloc as well) is not always guaranteed to return the requested reallocation. It may or may not succeed all the time.
I fixed the problem with the following code.
typedef struct CArrPtr {
unsigned char* ptr;
size_t size;
} CArrPtr;
void xtndc ( CArrPtr *bytesRef, uint8_t count );
. . .
CArrPtr xtnd = { .ptr = malloc(4), .size = 4 };
xtndc( &xtnd, 4 );
// xtnd.size is now 8 bytes
. . .
void xtndc ( CArrPtr *bytesRef, uint8_t count ) {
unsigned char *nptr;
if((nptr = realloc(bytesRef->ptr, bytesRef->size + count)) != 0)
{
bytesRef->ptr = nptr;
bytesRef->size = bytesRef->size + count;
}
}
As I am somewhat new to C, what I learned from this is that malloc specifically creates a pointer to a memory block, but you have no direct access to information about the memory block. Instead, you must store the size of the array that you created with malloc somewhere as well.
Since in the past I'd been initializing arrays with unsigned char arr[size]; and then using sizeof on it, I was under the impression that sizeof returned the size of the array, which is of course wrong as it gives you the size of a type.
Glad I could learn something from this.
sizeof is used to calculate size of data type or array. Pointer and array are very similar, but they are different things. For int *ap, sizeof(ap) will return 4 on x86, sizeof(*ap) will return 4; for int a[10], sizeof(a) will return 40.
sizeof expression is processed at compile time, so it will be a constant written into the executable file before you run the program.
malloc and realloc don't maintain size.
If realloc succeeds, it will reallocate the requested size. So you don't need to check the size after realloc returns, but you should check the return value of realloc to ensure that realloc succeeds.

Trouble with malloc

I have the following struct
struct NETWORK_ENDPOINT {
unsigned char Type;
unsigned char Protocol;
unsigned char IPv4[IPV4SIZE + 1];
unsigned int PortNumber;
unsigned char SocketIndex;
unsigned char RESERVED;
unsigned char *InboundData;
unsigned int InboundDataSize;
unsigned char *OutboundData;
unsigned int OutboundDataSize;
};
In the code I'm allocating with :
struct NETWORK_ENDPOINT *Endpoint = malloc(sizeof(struct NETWORK_ENDPOINT));
Then later in the code I'm allocating the OutboundData with.
Endpoint->OutboundData = malloc(20); // malloc() size may vary,
// but in the problem situation it is 20
Then I do :
memcpy(Endpoint->OutboundData, Data, 20);
Then the problem : From the debugger I can see that Endpoint is given address #0x1fd6, and the OutboundData is given address #0x1fca, so only 12 between. Shouldn't is be atleast 20 ?
The memcpy() function then will fill out in OutboundData ( can see in memory that data is correctly placed ), but once it passes 12 bytes, it will begin overwriting the start of the struct Endpoint, corrupting the Type and Protocol and half the IP, thereby making it useless afterwards.
anyone got any idea what I'm going wrong here ? Been working on this for days now, but whatever I try it does not fix this issue...
Have tried to increase the HEAP size, but it seems to stay at 12 bytes between the two memory locations no matter what I do..
OutboundData is given address #0x1fca, so only 12 between
Why you're interested in the address of OutboundData?
After malloc(), you should be checking the value of OutboundData, however, you won't be knowing the size of allocated memory thr' this.
Just to be clear, you're not copying to the address of OutboundData, rather , you are copying to the address pointed by OutboundData.
Then,
but once it passes 12 bytes, it will begin overwriting the start of the struct Endpoint, corrupting the Type and Protocol and half the IP, thereby making it useless afterwards.
No, it won't. The value and address of OutboundData are different and the value of OutboundData is used in memcpy().
IMHO, as long as
malloc() is success
Data is atleast of size 20 (for this case)
your memcpy() should work fine.

Working with large integer arrays

How to work with large integer, do I need GMP libraries or something?
I want an array that has elements starting from 0 to 2^32
How to get this to work:
#include <stdio.h>
int main(){
unsigned int i,j=0,sz=4294967295;
unsigned int A[sz];
A[j]=0;
for(i=1;i<=sz;i++){
A[i]=A[j]+1 ;
j++;
printf("%u\n",A[i]);
}
return 0;
}
error: process exited with return value 3221225725
is it that the array is too big or something??
According to Google, your A array is approximately 17 gigabytes. That's a lot. You're probably overflowing the stack.
If you really need this much memory, you may be able to malloc() it instead, but on older 32-bit architectures, you're basically out of luck (address space has a hard upper limit of 4 GB, minus kernel space).
You are allocating an array of 16-17GB which overflows the stack.
As haccks said you can try allocating on heap.
unsigned int *A = malloc(sizeof(int)*sz);
if(A == NULL) {
printf("Unable to allocate memory for array.\n");
exit(1);
}
Don't forget to free afterwards:
...
free(A);
return 0;
}
And you also have a bug in your code. Array is indexed from 0 to size - 1.
This will when i becomes sz write to invalid memory.
for(i=1;i<=sz;i++) { // Will cause invalid memory write
A[i]=A[j]+1 ;
j++;
printf("%u\n",A[i]);
}
Change to:
for(i=1; i < sz; i++) {
A[i] = A[j] + 1;
j++;
printf("%u\n", A[i]);
}
Memory for arrays is allocated on stack and its size is generally small and will result in stack overflow. You need to allocate memory on heap for such a large array. Either place
unsigned int A[429496729];
out side the main or use dynamic memory allocation
unsigned int *A = malloc(sizeof(int)*sz);
if(A == NULL)
exit(0);
Use free(A) to free the allocated memory once you are done with A.
Better use define constants from limits.h, such as UINT_MAX or ULONG_MAX, and check what type is used for indexing of arrays (perhaps your unsigned int transformed to int)

Segmentation fault in C while declaring large pointer array

I run in a problem with a program and I'm not sure how to solve it. I'm processing a file and to do so I get the size with ftell and store it in M_size. After that I declare a unsigned char pointer array with N. The array is then used in two functions a() and b().
...
unsigned long N = (M_size/ x);
int LstElemSize = M_size % x;
if(LstElemSize != 0){
N += 1;
}
unsigned char *ptr_M[N]
a(ptr_M)
b(ptr_M)
...
Function a() actually initializes each element of ptr_M in a for loop:
a(){
int i;
for(i = 0; i < N-1; i ++){
ptr_M[i] = malloc(sizeof(unsigned char) * x);
}
}
Function b() iterates then over each element and calculates stuff and at the end each element is freed.
My problem is now that when I try to process a file e.g. 1 GB the array size will be around 4 000 000 and a Segmentation error occurs (In the line i declare my array). If I calculated it correctly that is 8 byte (char pointer) times 4 000 000 = 32MB. The server running the program has enough memory to hold the file, but i guess as mentioned in Response 1 the stack space is not enough.
What can I do to solve my problem? Increase my stack space? Thanks!
The problem is that you're defining ptr_M in the stack, which has a small size limit. The heap does not have such a small size limit and is able to use more of your system's memory. You need to use malloc() to allocate ptr_M just like you allocate the subarrays. (Make sure to free it at some point too along with all those subarrays!)
unsigned char **ptr_M = malloc(sizeof(unsigned char*) * N);
Also, your a() has an off-by-one error. It ignores the last item of the array. Use this:
for(i = 0; i < N; i ++){
unsigned char *ptr_M[N] is a variable-length array declaring N number of unsigned char on the stack in your case. You should dynamically allocate the space for the array as well.
unsigned char **ptr_M = malloc(sizeof(unsigned char*) * N);
a(ptr_M);
b(ptr_M);
...
//After you free each element in ptr_M
free(ptr_M);
malloc allocates space from heap, not from stack. You may try increasing your heapsize looking at the compiler option. Check the upper limit of heapsize that is supported there.

Resources