I'm working on a linking program, consisting of two files. The function createArray() creates an array of some length, which stores random numbers between 0 and 3. It's part of the second file, which gets linked with the first file to create a big program when it's compiled. I have all the declarations from the first file, including the extensions. Anyway, I compile and run the program, but I get a Segmentation Fault error, which I'm assuming it comes down to the line that actually puts the random number into the array.
int length;
int* intArray;
int maxRandVal;
void createArray(){
length = 16;
maxRandVal = 3;
intArray[length];
int i = 0;
for (i; i < length; i++){
int r = rand() % (maxRandVal+1);
intArray[i] = r;
}
}
I believe my error is that I'm trying to place an integer into a pointer array - something that I still don't understand how it works. How could I insert my random number into a pointer array?
Allocate memory for it first using malloc.
intArray = malloc(sizeof(int)*length);
The way you have done does not work. intArray[length]
Dont forget to free that memory once you are done with it .
Where is the intArray pointing to? Allocate memory using malloc for length 16.
intArray = malloc(sizeof(int)*length);
And what are you trying to achive by this:?
intArray[length];
Related
Say I want to loop over an array, so I used a basic for loop and accessed each element in it with the index but what happens if I don't know how long my array is?
#include <stdio.h>
#include <stdlib.h>
int main(){
int some_array[] = {2,3,5,7,2,17,2,5};
int i;
for (i=0;i<8;i++){
printf("%d\n",some_array[i]);
}
return 0;
}
This is just a simple example but if I don't know how big the array is, then how can I place a correct stopping argument in the loop?
In Python this is not needed since the StopIteration exception kicks in, but how can I implement it in C?
Just do like this:
for (i=0; i<sizeof(some_array)/sizeof(some_array[0]); i++){
printf("%d\n",some_array[i]);
}
But do beware. It will not work if you pass the array to a function. If you want to use it in a function, then write the function so that you also pass the size as argument. Like this:
void foo(int *arr, size_t size);
And call it like this:
foo(some_array, sizeof(some_array)/sizeof(some_array[0]));
But if you have a function that just take a pointer, there is absolutely no standard way to find out the size of it. You have to implement that yourself.
You have to know the size of the array. That's one of the most important rules of C programming. You, the programmer, are always responsible for knowing how large your array is. Sure, if you have a stack array or a static array, you can do this:
int array[size];
int size_of_array = sizeof array / sizeof *array;
for (int i = 0; i < size_of_array; i++) {
// do something with each array[i]
}
But as you can see, you needed the variable size in the first place. So what's the point of trying to discover the size if you were forced to know it already?
And if you try to pass this array to any function
some_function(array); /
you have to pass the size of the array too, because once the array is no longer in the same function that declared it, there is no mechanism to find its size again (unless the contents of the array indicate the size somehow, such as storing the number of elements in array[0] or using a sentinel to let you count the number of elements).
void some_function(int *array) {
/* Iterate over the elements until a sentinel is found.
* In this example, the sentinel is a negative number.
* Sentinels vary from application to application and
* implicitly tell you the size of the array.
*/
for (int i = 0; array[i] >= 0; i++) {
// do something with array[i]
}
}
And if it is a dynamically-allocated array, then you need to explicitly declare the number of elements anyway:
int size = 10;
int *array = malloc(sizeof *array * 10);
So, to summarize, you must always know the size of the array. There is no such thing in C as iterating over an array whose size you don't know.
You can use sizeof() to get the size of the array in bytes then divide the result by the size of the data type:
size_t n = sizeof(some_array)/sizeof(some_array[0]);
In general, you can calculate the size of the array with:
sizeof(ArrayName)/sizeof(ArrayType)
but this does not work with dynamically created arrays
I am converting a program from fortran77 to C Programming Language, In the fortran program a 5D array is declared as shown below, and the code compiles and executes well. But when I convert the same code to C with the same values, the C code compiles but it gives Segmentation fault.
If this issue is because of the different standard layout of multidimensional arrays memory allocation between the two languages, I have tried all dimension combinations while declaring the array in C, and in all cases it also gives a 'Segmentation fault'.
I have also tired the 'calloc' technique shown below, and it works but I don't know how to assign values to the globally declared array.
Note: The segmentation fault is at the declaration step (i.e. The program stops there)
So basically my questions are:
- Why does it works in fortran but not in C ?, and,
- How to solve this issues in C ?
! Fortran77 Code
parameter (i2maxbin=38)
parameter (imaxbin=20)
parameter (Nid=10)
real*8 dNdpt(Nid,i2maxbin,imaxbin,imaxbin,imaxbin)
/* C Code */
const int i2maxbin = 38;
const int imaxbin = 20;
const int nID = 10;
double dNdpt[nID][i2maxbin][imaxbin][imaxbin][imaxbin];
/* Declaring using calloc */
double (*dNdpt)[nID][i2maxbin][imaxbin][imaxbin][imaxbin] =
calloc(sizeof(*dNdpt), 38);
for(int i = 0; i < nID; i++)
{
for(int j = 0; j < i2maxbin; j++)
{
dNdpt[i][j][0][0][0] = 12.22673423;
}
}
When executing it gives me this error
error: assignment to expression with array type
dNdpt[i][j][0][0][0] = 12.22673423;
^
the following proposed code:
places the array in file scope rather than on the stack
cleanly compiles
avoids the use of dynamic memory allocation/free'ing
cleanly runs and exits without crashing
avoids using VLAs
And now the proposed code:
#define i2maxbin 38
#define imaxbin 20
#define nID 10
double dNptr[nID][i2maxbin][imaxbin][imaxbin][imaxbin];
int main( void )
{
for(int i = 0; i < nID; i++)
{
for(int j = 0; j < i2maxbin; j++)
{
dNptr[i][j][0][0][0] = 12.22673423;
}
}
}
The stack size in C and also in C++ is very limited, generally, a 1D-array of maximum 1e5 size is allowed, and if we assume "double" size as 8 bytes then that translates into maximum memory of 8*1e5 bytes.
Now, let's look at your 5D-array, it's trying to allocate 10*38*20*20*20 = 3,040,000 "double" units which when converted into the memory is 24,320,000 bytes which is well above the allotted stack size in C or C++.
That's why you are getting a SEG-FAULT.
You can try initializing the array globally that way it is allocated heap memory which is typically bigger than the stack memory, even then the max size is limited to 8*7*1e5 bytes at max(depends on your machine).
You solve it by creating the array on the heap instead of the stack.
double* dNdpt = malloc(sizeof(double)*nID*i2maxbin*imaxbin*imaxbin*imaxbin);
then keep track of where you are in this gigantic array by calculating the index
a simpler example :
double* my2dim = malloc(sizeof(double)*10*20); // 10 rows 20 cols
my2dim[3][2] = 10.0 would be written *(my2dim + 3 * 20 + 2) = 10.0;
I have had a look around but have not been able to find an answer to this question already. I am trying to create a hash table of which each element is a struct. In each struct is a variable to let the program know if the cell has been occupied, for this to work I need to set all of them to zero. The thing is it worked fine but now and then (seemingly randomly) I'd get an access violation. I thought I fixed it but when I come to grow my array the error creeps up again, leading me to believe that I have made an error. My pointer knowledge is not that good at all, so any help would be appreciated. This is what the function looks like:
HashTableCell *initialiseTable(HashTableCell *hashTable, int *tableSizePtr)
{
int i = 0;
int totalSize = *tableSizePtr * sizeof(HashTableCell);
HashTableCell *tempStartingcell;
tempStartingcell = (HashTableCell*)malloc(sizeof(HashTableCell));
*tempStartingcell = *hashTable;
while (i <= *tableSizePtr)
{
/*we keep moving forward, need to use the first entry*/
*hashTable = *(tempStartingcell + (i * sizeof(HashTableCell)));
hashTable->isOccupied = 0;
i++;
}
free(tempStartingcell);
return hashTable;
}
And before I malloced some space for the table and passed it in another function like so:
HashTableCell *hashTable;
hashTable = (HashTableCell*)malloc((sizeof(HashTableCell)*tableSize));
hashTable = initialiseTable(hashTable, tableSizePtr);
The idea is to start at the beginning and move along the correct number of spaces along per iteration of the while loop. When I come to resize I merely make a new array with double the malloced space and pass it to the initialise function but this throws up an access violation error at seemingly random indexes.
I am using VS2015 if that helps anything.
Thank you for your help.
The problem is in this line:
*hashTable = *(tempStartingcell + (i * sizeof(HashTableCell)));
When you are adding an integer to a pointer, C and C++ already take into account the size of the array elements, so you should not multiply with sizeof(HashTableCell), but rather do:
*hashTable = *(tempStartingcell + i);
Otherwise, your extra multiplication will cause an access outside of the tempStartingCell array. It makes even more sense to write it like this:
*hashTable = tempStartingcell[i];
But there is more wrong with your code; if you just want to set isOccupied to zero for each element in hashTable, just do:
void initialiseTable(HashTableCell *hashTable, int tableSize)
{
for (int i = 0; i < tableSize; i++)
hashTable[i].isOccupied = 0;
}
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.
I am new to C and was writing a function to insert an element to sorted list. But my code does not display the last digit correctly. Though i know there are variety of ways to correct it but i want to know why my code isnt working, here's the code
#include <stdio.h>
int insert(int array[],int val);
int main (void)
{
int arr[5],j;
for (j = 0; j<5; j++)
{
scanf("%d",&arr[j]);
}
insert(arr,2);
for(j = 0;j<6;j++)
printf("%d",arr[j]);
return(0);
}
int insert(int array[],int val)
{
int k,i;
for (k = 0;k<5;k++)
if(val<array[k])
break;
for (i = 4; i>=k;i--)
{
array[i+1] = array[i];
}
array[k] = val;
return(1);
}
You are writing out of the range of the array here:
for (i = 4; i>=k;i--)
{
array[i+1] = array[i];
Where i+1 == 5 and you array has a range of 0 ...
4
Then you try to print the array but you go out of bounds again:
for(j = 0;j<6;j++)
printf("%d",arr[j]);
First make sure your array is large enough.
When you give a static / auto array to a function for insertion of elements, you must give: Address, Valid length, and Buffer Space unless guaranteed large enough.
When giving a dynamically allocated array, you must give pointer and valid length, you might give buffer space or guarantee enough space left to avoid reallocations.
Otherwise, you risk a buffer overrun, and UB means anything may happen, as in your example.
You're trying to make arr[6] out of arr[5] adding one val - it's impossible in C using statically allocated arrays.
To accomplish what you're trying to do you'd need to use dynamical arrays allocation:
int *arr;
int N = 5;
arr = (int *)malloc(N*sizeof(int));
then you use this arr same way as you did with arr[5] for loading data here via scanf.
And later on , while adding extra value to array - you'd need to reallocate your arr to make it bigger (read about malloc/realloc C functions):
arr = (int *)realloc((N+1)*sizeof(int));
Now your arr is of 6 int-s size.
Unfortunately if you don't know array sizes (number of elements) a priori you would need to deal with dynamical memory allocations in C.
Don't forget to release that memory in the end of the main() function:
free(arr);
You have to increase your array size from 5 to 6 as you are inserting one new element in your array, so there should be some space for that.
int arr[6];
you can also find more information in the link below:
https://learndswithvishal.blogspot.com/2020/06/insert-element-in-sorted-array.html