I have a program that deals with very large arrays, and when I'm trying to populate the array with random values, it always segfaults at a specific index. On Mac OSX 10.10 running XCode, it segfaults at index 1000448, and on GCC targeting LLVM version 6.1.0 it faults at 1001472.
Here is my code
#include <stdlib.h>
#include <stdio.h>
#define WIDTH 1000
#define HEIGHT 1000
/////////////////////////////////////////////////////////
// Program main
/////////////////////////////////////////////////////////
int main(int argc, char** argv) {
// set seed for rand()
srand(2006);
// 1. allocate host memory for matrices A and B
unsigned int length = WIDTH * HEIGHT;
unsigned int size = sizeof(int) * length;
printf("%i", size);
int* matrixA = (int*) malloc(size);
for(int i = 0; i < size; i++) {
printf("%i\n", i);
matrixA[i] = rand() % 10;
}
free(matrixA);
}
Why is this segfaulting? I checked the size allocated to matrixA, and it appears to be the correct size (4,000,000)
the following code
compiles cleanly
performs the appropriate error checking
#include <stdlib.h>
#include <stdio.h>
#define WIDTH (1000)
#define HEIGHT (1000)
/////////////////////////////////////////////////////////
// Program main
/////////////////////////////////////////////////////////
int main( void )
{
// set seed for rand()
srand(2006);
// 1. allocate host memory for matrices A and B
unsigned int length = WIDTH * HEIGHT;
unsigned int size = sizeof(int) * length;
printf("%u\n", size);
int* matrixA = NULL;
if( NULL == (matrixA = malloc(size) ) )
{// then malloc failed
perror( "malloc failed");
exit( EXIT_FAILURE );
}
// implied else, malloc successful
for(unsigned i = 0; i < length; i++)
{
printf("%i\n", i);
matrixA[i] = rand() % 10;
}
free(matrixA);
} // end function: main
Oops, I just realized what the problem was. I'm looping from 0 to size, instead of length. If someone could tell my why those particular values, though, it would be great
Related
I am re-studying C right now and I have always been told that in C we have to define which maximum size would have an array so it can have enough space reserved in the memory. I mean this:
#include <stdlib.h> //Para funciĆ³n malloc
int main() {
int *enteros = malloc( sizeof(int) * 10 ); //An array of 10 integers
int i;
for(i = 0; i < 100; i++) {
enteros[i] = i*10;
printf( "-> enteros[%d] = %d\n", i, i*10 );
}
}
However, the following code works well (here I am not telling the max size, I just allocate enough memory for the pointer to int), and I just can't find an answer to what it's happening here.
#include <stdio.h>
#include <stdlib.h>
int main() {
int *enteros = malloc( sizeof(int) );
int i;
for(i = 0; i < 2000; i++) {
*(enteros++) = i*10;
printf( "-> enteros[%d] = %d\n", i, i*10 );
enteros++;
}
}
It seems that I just can manage dynamic arrays perfectly well, without having to reallocate memory for the array and being forced to introduce a starting size, however I feel that I'm missing something.
Yes, you can compile and run the code, but you may write data to addresses reserved by other variables.
But this is just a source of the problem. The actual problem is that you are getting unexpected program behavior and run time errors extremely hard to find if you have large volume of code and with allocation issue inside. And it can be dramatic if happens on production. This cannot happen in most of other languages, but in C a developer is responsible.
Try this code as an example:
#include <stdio.h>
#include <stdlib.h>
int main() {
int *enteros = malloc( sizeof(int) );
int *a = malloc( sizeof(int));
int i;
*a = 4; // value setup
for(i = 0; i < 2000; i++) {
*(enteros++) = i*10;
printf( "-> enteros[%d] = %d\n", i, i*10 );
enteros++;
}
printf( "a = %d\n", *a); // value changed!!!
}
Then comment out to double check:
#include <stdio.h>
#include <stdlib.h>
int main() {
int *enteros = malloc( sizeof(int) );
int *a = malloc( sizeof(int));
int i;
*a = 4;
for(i = 0; i < 2000; i++) {
// *(enteros++) = i*10;
// printf( "-> enteros[%d] = %d\n", i, i*10 );
enteros++;
}
printf( "a = %d\n", *a); // value did not change
}
https://repl.it/repls/SoggyOverdueFactors
One have to specify size of array while dynamic allocation using malloc/new.
I would like to know why the first two elements are always non-zero. I don't know how more I can describe the question, but this is not allowing me to post the question, so I'm writing this. Not sure if this will work.
#include <stdio.h>
#include <stdlib.h>
#define SIZE 3
void printMatrix(int **m)
{
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++)
printf("%d ", m[i][j]);
printf("\n");
}
}
int main(int argc, char const *argv[])
{
int **matrix;
matrix = (int **) calloc(sizeof(int), SIZE);
for (int i = 0; i < SIZE; ++i)
matrix[i] = (int *) calloc(sizeof(int), SIZE);
printf("%s\n", "Matrix initialized.");
printMatrix(matrix);
return 0;
}
Output:
Matrix initialized.
1371548192 32653 0
0 0 0
0 0 0
You're not allocating enough memory:
matrix = (int **) calloc(sizeof(int), SIZE);
Here you're attempting to create an array of 3 int *, but you're only allocating space for 3 int. If a pointer is larger than an int on your system, which it most likely is, you write past the end of the array when you create the arrays for each row. Writing past the end of allocated memory invokes undefined behavior.
Since you're creating an array of int *, use that for the size of each element:
matrix = calloc(sizeof(int *), SIZE);
Also, don't cast the return value of malloc/realloc/calloc, as that can mask a bug if you forget to #include <stdlib.h>
The code uses calloc(sizeof(int), SIZE), but the actual datatype in the structure is int *, leading to insufficient memory allocation on some systems (mine gives int size as 4 and int * size as 8).
Here's a rewrite suggestion (we'll swap size parameters in the calloc call per its header):
int main(int argc, char const *argv[]) {
int **matrix;
if (!(matrix = calloc(SIZE, sizeof(*matrix)))) {
fprintf(stderr, "calloc failed");
return 1;
}
for (int i = 0; i < SIZE; ++i) {
if (!(matrix[i] = calloc(SIZE, sizeof(*(matrix[i]))))) {
fprintf(stderr, "calloc failed");
return 1;
}
}
printf("%s\n", "Matrix initialized.");
printMatrix(matrix);
return 0;
}
Here, we use *matrix and *matrix[i] instead of hard coding the types int * and int respectively. This can help us avoid bugs and hunting for locations to change code if we need to make type adjustments at some point.
We also check that calloc succeeds by testing that the pointer is non-NULL. Failing to do so can introduce difficult-to-find bugs due to undefined behavior.
Note Do I cast the result of malloc?.
Reference manual describes calloc as:
void* calloc (size_t num, size_t size);
So, calloc takes firstly num of elements and then size of a particular element
Try:
matrix = (int **) calloc(SIZE, sizeof(int *));
I have written a cuda program to do some operation on large array. But when I pass that array to a cuda kernel, then all of its elements are not accessed by threads. Below, there is a simple program explaining my use case:
#include <stdio.h>
#include <stdlib.h>
__global__
void kernel(int n){
int s = threadIdx.x + blockIdx.x*blockDim.x;
int t = blockDim.x*gridDim.x;
for(int i=s;i<n;i+=t){
printf("%d\n",i); //printing index of array which is being accessed
}
}
int main(void){
int i,n = 10000; //array_size
int blockSize = 64;
int numBlocks = (n + blockSize - 1) / blockSize;
kernel<<<numBlocks, blockSize>>>(n);
cudaDeviceSynchronize();
}
I've tried with different blockSize = 256, 128, 64, etc, It is not printing all the indices of array. Ideally, it should print any permutation of 0 to n-1, however it is printing lesser(<n) numbers.
If numBlocks and blockSize both are 1, then it is accessing all the element. And if array size is less than 4096, then also it is accessing all the elements.
Actually, all of the values are being printed in the current case. but you may not be able to see all of them due to buffer limit of the output console. Try increasing the output console's buffer size.
Additionally, keep in mind that the printf calls inside the kernel execute out-of-order. Also, there are limitations of the printf buffer on the device which are explained in the documentation.
Use better debugging techniques! Your code is properly functional
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
#include <stdlib.h>
__global__
void kernel(int* in, int n){
int s = threadIdx.x + blockIdx.x*blockDim.x;
int t = blockDim.x*gridDim.x;
for (int i = s; i<n; i += t){
in[i] = 1; //printing index of array which is being accessed
}
}
int main(void){
int i, n = 10000; //array_size
int blockSize = 64;
int numBlocks = (n + blockSize - 1) / blockSize;
int* d_res,*h_res;
cudaMalloc(&d_res, n*sizeof(int));
h_res = (int*)malloc(n*sizeof(int));
kernel << <numBlocks, blockSize >> >(d_res, n);
cudaDeviceSynchronize();
cudaMemcpy(h_res, d_res, n*sizeof(int), cudaMemcpyDeviceToHost);
int sum = 0;
for (int i = 0; i < n; i++)
sum += h_res[i];
printf("%d", sum);
}
I want to write a C function that gets: a seed, int n (the number of random ints to generate), and upper limit (the max allowed number).
I came so far as to have somthing like this:
// I need a function definition here
// I forgot how to allocate the int array ... somehting with 'sizeof'?
srand(time(NULL)); //seed for rand
for(i = 0; i < length; i++)
array[i] = rand()%upperLimit;
return array;
Then I probably need those header files:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
You need #include <time.h> for the time function.
This is simple program matching your description with comments in the code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int *
alocate (unsigned int n)
{
return malloc (n * sizeof (int)); // allocate memory block for n numbers and return int pointer to it
}
int *
generate_block_with_random_numbers (unsigned int n, int upper_limit)
{
// function `int *generate_block_with_random_numbers(unsigned int n, int upper_limit)`
// gets a positive integer n as an argument
// reserves the n block of int variables in memory
// fills this block with random values
// returns a pointer to the beginning of the reserved block.
srand (time (NULL)); // seed generator
int *array = alocate (n); // note: array pointer always points to the beginning of the allocated memory
for (int i = 0; i < n; i++)
{
// you can index the array moving to its next element via [i]
array[i] = rand () % (upper_limit+1); //
}
return array;
}
int
main ()
{
unsigned int n = 5;
unsigned int upperL = 5;
int *block = generate_block_with_random_numbers (n, upperL);
// Display the data contained in the returned block:
for (int i = 0; i < n; i++)
{
printf ("%d\n", block[i]); // print it
}
return 0;
}
Output:
5
0
2
3
3
I want to fill big array with rand() function, when I define my array by int h_in[N],the program crash in vs 2010,to my surprise, when I copy it to the online complier ideone a linkand everything is ok.Finally I define array by h_in = (int *)malloc(N * sizeof(int)) in VS 2010,the program works.I can't figure out that and hope somebody point out my error.
#include <stdio.h>
#include <stdlib.h>
const int N = 1024 * 1024;
int main()
{
//int *h_in = (int *)malloc(N * sizeof(int));
int h_in[N];
float sum = 0.0f;
srand(1);
for(unsigned int i = 0; i < N; i++) {
h_in[i] = (rand() & 0xFF);
}
return 0;
}
int h_in[N];
is allocated on the stack.
int * h_in = malloc(N * sizeof(int));
is allocated on the heap. [BTW: don't cast the result of malloc()]
The default stack size is 1MB, so you should use a linker option to increase it:
/F (Set Stack Size)