End of dynamically allocated array [duplicate] - c

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);
}
}

Related

Segmentation fault when using sprintf in dynamically allocated array

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.

c programming encounters Segmentation fault (core dumped)

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.

Seg Fault when accessing an array initialised with malloc

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.

Precise Syntax for Accessing Elements in a 2D Array - by Pointer?

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);

How to realloc based on size of array?

Say you malloc enough memory space to hold an array of size 20. The program is running and now I need enough memory for an array of size say 40. I tried to do this using realloc but it doesn't seem to be working. My code is the following(I'm trying to find the sum of all even-valued fibonacci terms below 4million):
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv){
int i,sum,size;
int *fibo;
size = 20; //initial size of array
fibo = (int *) malloc(size*sizeof(int));
fibo[0]=1;
fibo[1]=1;
i=2;
sum=0;
while(fibo[i-1]<4000000){
fibo[i] = fibo[i-1]+fibo[i-2];
printf("fibo[%d] = %d\n", i, fibo[i]);
if(fibo[i]%2 == 0){
sum+= fibo[i];
}
i++;
if(i>size){
fibo = (int *) realloc(fibo, (size *= 2)*sizeof(int));
}
}
printf("Sum = %d\n", sum);
return 0;
}
Anyone know why realloc is failing, and how I can fix it?
During the last iteration, i equals 20 but the expression
if(i>size)
is false, so you do not actually use realloc, then by writing to
fibo[20]
the program is accessing part of the memory that does not belong to it. Changing the expression to
if(i>=size)
should fix it :)

Resources