I am trying to allocate a big block of memory.
I ran this code firt,
#include <stdio.h>
#include <stdlib.h>
int main()
{
long i;
long n = 50000;
printf("trying to malloc %ld memory. ", n);
long *ptr;
ptr = (long*) malloc(n * sizeof(int));
if(ptr == NULL)
{
printf("Error! memory not allocated.");
exit(0);
}
for(i = 0; i < n; ++i)
{
*(ptr+2*i) = 9;
}
for(i = 0; i < 5; ++i)
{
printf("%ld ", *(ptr+2*i));
}
return 0;
}
and then I got this error
Segmentation fault (core dumped)
I know this "you are accessing memory that does not belong to you.", but why
PS:
long n = 5000; works well
When you have a pointer to a datatype, adding 1 to that pointer will actually offset the address by however large the datatype is. If I have a pointer to an integer array at 0x0000, doing myArray += 1; will result in my pointer having the value of 0x0004 (assuming an integer is 4 bytes on my system)
Knowing this, you can see how the line *(ptr+2*i) will go out of the bounds of your array for all values of i greater than i/2
Normally, since you are dynamically creating this array, writing to these addresses would just corrupt heap memory and not cause a segfault. The problem is that your program is going so far out of bounds, it is past the heap and going into memory that doesn't belong to your program. This is why it segfaults for 50000 and not 5000.
Related
I am converting integers to strings and adding them to a dynamically allocated array. The problem is that it is causing a segfault. I don't understand why it is happening.
#include <stdio.h>
#include <stdlib.h>
int main() {
char *x = malloc(10 * sizeof(char));
x[0] = malloc(10 * sizeof(char));
sprintf(x[0],"%d",10);
for(int i = 0; i < 10;i++){
free(x[i]);
}
free(x);
return 0;
}
To allocate an array whose elements are char*, the pointer to point the array should be char**, not char*.
Also you mustn't use values in buffer allocated via malloc() and not initiaized. The values are indeterminate and using them invokes undefined behavior.
#include <stdio.h>
#include <stdlib.h>
int main() {
/* correct type here (both variable and allocation size) */
char **x = malloc(10 * sizeof(char*));
x[0] = malloc(10 * sizeof(char));
sprintf(x[0],"%d",10);
/* initialize the other elements to pass to free() */
for (int i = 1; i < 10; i++) x[i] = NULL;
for(int i = 0; i < 10;i++){
free(x[i]);
}
free(x);
return 0;
}
If you want a dynamic allocated array of strings, you should declare your variable x as a pointer to an array of e.g. 32 chars. The you can allocate/deallocate an array of these using a single malloc and likewise a single free.
Like:
#define NUM_STRINGS 10
#define STRING_SIZE 32
int main() {
// declare x as a pointer to an array of STRING_SIZE chars
char (*x)[STRING_SIZE];
// Allocate space for NUM_STRINGS of the above array, i.e.
// allocate an array with NUM_STRINGS arrays of STRING_SIZE chars
x = malloc(NUM_STRINGS * sizeof *x);
if (x)
{
for (int i = 0; i < NUM_STRINGS; ++i)
{
sprintf(x[i], "%d", 10 + i);
}
for (int i = 0; i < NUM_STRINGS; ++i)
{
puts(x[i]);
}
free(x);
}
return 0;
}
Output:
10
11
12
13
14
15
16
17
18
19
The best way to determine the amount of memory to be used with malloc is this:
#include <stdio.h>
#include <stdlib.h>
#define N_STRINGS 10
#define STRING_SZ 10
int main() {
// if you use *x (the deferred subexpression) the compiler can calculate its
// sizeof easily, and no need to use a constant or something that has to be
// revised if you change the type of x. Also, calloc will give instead N_STRINGS
// pointers already initialized to NULL.
char **x = calloc(N_STRINGS, sizeof *x);
// to be able to free(x[i]) for all i, you need to initialize all pointers,
// and not only the first one.
int i; // I prefer this, instead of for(int i..., which is more portable with legacy code.
for (i = 0; i < N_STRINGS; i++) {
// char is warranted to be sizeof 1, you don't need to specify but the
// number of chars you want for each character array.
x[i] = malloc(STRING_SZ); // remember only STRING_SZ chars you have, so...
// better to use snprintf(), instead.
snprintf(x[i], // the buffer pointer
STRING_SZ, // the buffer size (STRING_SZ chars, incl. the final null char)
"%d", // the format string
10); // initialize all strings to the string "10" ???
}
// upto here we have made N_STRINGS + 1 calls to malloc...
// you should do something here to check that the allocations went fine, like
// printing the values or do some work on the strings, but that's up to you.
// now, everything should be fine for free() to work.
for(int i = 0; i < N_STRINGS; i++){
free(x[i]);
}
free(x); // ... and this is the N_STRINGS + 1 call to free.
return 0;
}
Check always that the number of free calls executed by your program has to be the same of the malloc calls you have made (before). A free call must free the memory allocated by one (and only one) call to malloc. You cannot free something that has not been acquired by malloc() (or calloc()) directly or indirectly. The same as it is bad use (but not necessary an error) to do a malloc that is not freed before the program ends (this is not true in non-hosted environments, e.g. embedded programs, in which the operating system doesn't deallocate the memory used by a program when it finishes, although)
By the way, the reason of your segmentation fault is precisely that you have made only two calls to malloc(), but you made 11 calls to free(). free() tries to free memory that malloc() has not allocated, or even worse, you don't own. Anyway, this drives you to Undefined Behaviour, which is something you don't desire in a program. In this case, you got a program crash.
This question already has answers here:
Accessing an array out of bounds gives no error, why?
(18 answers)
Closed 2 years ago.
that's my first question. Sorry if I do something wrong. Thanks for your understanding.
I have a dynamically allocated array,
int *read_array(char *file_path , int *arr){
int max = 0 ,min = 0, i = 0;
FILE *fp = fopen(file_path,"r");
arr= malloc(1 * sizeof(int));
fscanf(fp, "%d,", &arr[i] );
max = arr[i];
min = arr[i];
i++;
arr = realloc(arr , i * sizeof(int));
while(fscanf(fp, "%d,", &arr[i] ) != EOF){
if(max < arr[i]){
max = arr[i];
}
else if(min > arr[i] ){
min = arr[i];
}
i++;
arr = realloc(arr , (i +1) * sizeof(int));
}
printf("%d\n",arr[i + 10]);
free(arr);
}
I tried to print what is at (i+10)th index of my array. It prints "0".
But when I made that printf like printf("%d\n",arr[i + 100000]); I got a seg fault as I expected. But I think I allocated as much memory as "i".
Why arr[i+10] is not giving seg fault ?
Thank you for your time.
This is an array-out-of-bounds logic error, but there's a good chance it's not throwing a segmentation fault because malloc allocated more memory than you were expecting.
The C standard does not require malloc() to return a pointer to exactly the amount of memory you asked for. The parameter you pass to malloc() is treated by the system as the minimum required size for the chunk of memory it returns to you.
It is not uncommon for the system to give you quite a bit more memory than you ask for for alignment and other complicated-operating-system reasons that coders really don't need to know about or understand.
Try compiling and running this program on your system to see proof of what I'm talking about:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define VALUE 150 //Or whatever you want
int main(){
for(int i=0;i<VALUE;++i){
void *pt=malloc((size_t)i);
printf("Asked for %d bytes, received %zd bytes\n",i,malloc_usable_size(pt));
free(pt);
}
}
This question already has an answer here:
Definitive List of Common Reasons for Segmentation Faults
(1 answer)
Closed 5 years ago.
My program need to have a function in which it finds the largest element of an array. It then returns the position of largest element. However, when finding the largest element, I am only allowed to use pointer arithmetic.
#include <stdio.h>
int *largest(int *array, int size){
int *p1 = array;
int *count, max = *p1;
for(*count = 0; count < p1 + size - 1; p1++){
if (max < *p1){
max = *p1;
count++;
}
}
return count;
}
int main(void){
int *array, size = 10;
printf("enter elements; ");
for(int i = 0; i < size; i++){
scanf("%d ", &array);
array++;
}
printf("\nThe largest element in the array is in element %d", *largest(array, size));
}
However, when I run the program, after enter values for the elements, it gives me:
segmentation fault (core dumped)
Mistakes in the function main:
You didn't allocate memory for the array. You need to add line array = (int*) malloc(sizeof(int) * size);. Without this line you get segmentation fault.
Another mistake is in filling array. Array is pointer already so you don't have to reference it again. Now you are changing pointer, not array values
Potential bug: In loop when you fill array, you increase pointer, so you loose information about beginning of array. You can get it again after loop doing array = array - size;, but it won't work if you break loop earlier. It is better to work with temporary pointer.
Mistakes in the function largest:
You created pointer count, which is not allocated and then in for loop initialization you write value 0 to unknown address. Causes segmentation fault.
In for loop you are trying to read memory from address 0 to address array + size - 2, but you want to read it from beginning of array to the end of array which is from array to array + size - 1.
Returning count makes no sense, but to sum it up, look at the example.
Pointer is just number which is address to memory, so when you don't allocate it or don't assign existing pointer, then it points randomly to memory and OS don't let you access that memory. It can happen that you will read something from random pointer, but new compilers sets initial value to 0. In BSD you can read from address 0, but linux cause segmentation fault (I hope that I didn't switch it). Writing to address 0 causes segmentation fault in both systems.
You should also check in function if you got valid pointer and allocation can fail so you need to check pointer immediatelly after allocation too. To sum this: Never trust pointer, always check it's validity.
Example doesn't check validity of pointers.
#include <stdio.h>
int *largest(int *array, int size){
int *end = array + size; // address behind array
int *max = *array; // address with largest value
for(; array < end; ++array){ // you dont need initialization since the array points to beginning
if (*max < *array){ // compare values, not address
max = array; // save position of pointer with largest value
}
}
return max; // return address with largest value
}
int main(void){
int *array, size = 10;
array = (int*)malloc(sizeof(int) * size); // allocate memory
printf("enter elements; ");
int *tmp = array; // temporary variable to not loose information about beginning of array
for(int i = 0; i < size; i++){
scanf("%d ", tmp); // reference is not needed since tmp is already pointer to value
tmp++;
}
printf("\nThe largest element in the array is in element %d", *largest(array, size));
}
Below is a simplified extract of a program I'm writing. I'm having issues accessing elements towards the end of the array.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(int n, char *args[n]){
// create 4D array scores[10000][100][100][100] on heap
uint64_t arraySize = 1; // this avoids overflow
arraySize *= 10000;
arraySize *= 100;
arraySize *= 100;
arraySize *= 100;
int (*scores)[10000][100][100] = malloc(arraySize);
for (int i = 0; i < 10000; i++) {
for (int j = 0; j < 100; j++) {
printf("%d, %d, %d\n", i, j, scores[i][j][0][0]);
}
}
}
The program loops through the 4D array score and as a test I'm printing the contents of the array. The loop starts off as planned, printing in the format "i, j, 0" for each i and j, until the last success "25, 0, 0".
From this point on I get random numbers rather than 0, starting with "25, 1, 1078528" up until "25, 45, 1241744152" which is then followed by "Segmentation fault (core dumped)".
After fiddling around I found the first non-zero array member to be scores[25][0][7][64].
So I guess I'm running out of space and so am accessing memory I shouldn't be? If anyone knows or has an idea as to how I could fix this I'd really appreciate it.
My PC is running Ubuntu 16.10 64bit, has 16GB RAM and 16GB swap
Edit
After implementing the following suggestions I get a return value of "calloc: Cannot allocate memory".
int (*scores)[100][100][100] = calloc(arraySize, sizeof(int));
if (scores == NULL) {
perror("calloc");
return 1;
}
If I comment out the new if statement (and run the for loop) I get an immediate seg fault. This also happens if I use malloc:
int (*scores)[100][100][100] = malloc(arraySize * sizeof(int));
Why could this be? Surely my system has enough memory
Cheers
Check the return value of malloc() and determine if it failed to allocate.
You forgot to multiply the size of int.
The type of result should be int (*)[100][100][100], not int (*)[10000][100][100].
Using value of buffer allocated via malloc() and not initialized invokes undefined behavior, so don't do that.
Try this:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(int n, char *args[n]){
// create 4D array scores[10000][100][100][100] on heap
uint64_t arraySize = 1; // this avoids overflow
arraySize *= 10000;
arraySize *= 100;
arraySize *= 100;
arraySize *= 100;
int (*scores)[100][100][100] = calloc(arraySize, sizeof(int));
if (scores == NULL) {
perror("calloc");
return 1;
}
for (int i = 0; i < 10000; i++) {
for (int j = 0; j < 100; j++) {
printf("%d, %d, %d\n", i, j, scores[i][j][0][0]);
}
}
}
Your pointer to a variable length array does not use correct array sizes.
The array is: [10000][100][100][100]
but the pointer is: [100][10000][100][100]
And you need to multiply the array size times the size of the object, in this case size of type int.
The pointer definition should be:
int (*scores)[100][100][100] = malloc(arraySize*sizeof(int));
The allocated elements are not initialized. Reading them will yield indeterminate values.
The correct type to store the size of bytes that need to be allocated, is size_t, not uint64_t.
One of the correct ways to allocate the array is:
const size_t bytes = sizeof( int[10000][100][100][100] );
int (*scores)[100][100][100] = malloc( bytes );
(This of course assumes that size_t can represent that value.)
Did you try:
int (*scores)[10000][100][100] = malloc(sizeof(int)*arraySize);
Bye.
I'm a CS student working on a homework assignment, and I need help with a C syntax issue. Yesterday in class, my professor said, "an int** pointer is a pointer to a 2D int array." This blew my mind.
Turns out, we have to write a C program which reads an int matrix from a file, then do operations on that matrix. For example, "matrix1.txt" might look like this:
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
...for a 5x3 matrix. I get the dimensions of the matrix from another file, which is a problem I've already solved. But the point is I have to dynamically allocate the matrix array using variables.
Here's my issue: Its easy enough to use an int** pointer to malloc() an Y-by-X array... but what's the syntax to access it? Here's my code:
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char *argv[]){
char *myFile = argv[1];
FILE *targetFile;
targetFile = fopen(myFile, "r");
if (targetFile == NULL)
return -1;
else {
// Successfully opened "matrix1.txt" file
int x, y; // dimensions of the array, learned elsewhere...
int i, j;
char* data = NULL;
int** matrix = (int**)malloc((x*y)*sizeof(int)); // allocate memory for an Y-by-X array
for(i=0; i<y; i++){
for(j=0; j<x; j++){
fscanf(targetFile, "%c ", &data);
matrix[i][j] = atoi(data); // program seg faults here
}
}
}
fclose(targetFile);
return 1;
}
The issue is the "matrix[i][j] = atoi(data);" line; I'm either using the wrong syntax or I haven't initialized the array. I can't tell which - the program seg faults IMMEDIATELY once I hit this line in the GDB debugger.
I'm sure this is a C 101 kind of question... but I post this because I've been reading a lot of different posts on 2D arrays and pointers, yet I can't seem to find an example that fits my precise situation. Can anyone help me out with this?
Thanks,
-ROA
The syntax used in
matrix[i][j] = atoi(data);
is not incorrect. It's the logic used to allocate memory that is wrong.
One way to allocate memory for the 2D array is:
// Allocate memory for y number of int*s.
int** matrix = malloc(y*sizeof(int*));
for(i=0; i<y; i++)
{
// Allocate memory for x number of ints.
matrix[i] = malloc(x*sizeof(int));
for(j=0; j<x; j++)
{
// Assign to the ints
matrix[i][j] = <some value>;
}
}
For reading the data, use
int data;
and
fscanf(targetFile, "%d", &data);
Then, the inner loop above can be updated to:
for(j=0; j<x; j++)
{
// Assign to the ints
fscanf(targetFile, "%d", &data);
matrix[i][j] = data;
}
Make sure to add code to release the dynamically allocated memory.
// Free the memory allocated for the ints
for(i=0; i<y; i++)
{
free(matrix[i])
}
// Free the memory allocated for the int*s
free(matrix);