I should be allocating enough memory for my char**. I used gdb and found the point of the segmentation fault. I've been stuck on this part for about an hour and can't seem to figure out why I'm segfaulting.
Output of program:
size: 10, 20
start: 1, 1
end: 10, 20
Segmentation fault (core dumped)
10 = m1.xsize
20 = m1.ysize
1 = m1.xstart
1 = m1.ystart
10 = m1.xend
20 = m1.yend
snippet of my code:
typedef struct mazeStruct
{
char** arr;
int xsize, ysize;
int xstart, ystart;
int xend, yend;
} maze;
/* read in the size, starting and ending positions in the maze */
fscanf (src, "%d %d", &m1.xsize, &m1.ysize);
fscanf (src, "%d %d", &m1.xstart, &m1.ystart);
fscanf (src, "%d %d", &m1.xend, &m1.yend);
/* print them out to verify the input */
printf ("size: %d, %d\n", m1.xsize, m1.ysize);
printf ("start: %d, %d\n", m1.xstart, m1.ystart);
printf ("end: %d, %d\n\n", m1.xend, m1.yend);
//allocating memory for 2d char array
m1.arr = (char**)malloc(m1.xsize+2 * sizeof(char*));
for(i = 0; i < m1.xsize+2; i++)
m1.arr[i] = (char*)malloc(m1.ysize+2);
/* initialize the maze to empty */
for (i = 0; i < m1.xsize+2; i++) <---- when i = 6 it seg faults
for (j = 0; j < m1.ysize+2; j++)
m1.arr[i][j] = '.';
Am I not allocating enough memory or what am I doing wrong?
Your expression:
m1.xsize + 2 * sizeof(char*)
is equivalent to:
(m1.xsize) + (2 * sizeof(char*))
due to precedence of operators, which is not what you want. You need to instead use:
(m1.xsize + 2) * sizeof(char*)
By way of example, let's say you have m1.xsize set to 20 and your pointer size is four bytes. Hence you need space for 22 pointers, which is 88 bytes. The expression m1.xsize + 2 * sizeof(char*) gives you 20 plus double the size of a pointer, totaling 28 bytes, nowhere near enough for what you want to do.
As an aside, you should also stop casting the return value of malloc() since it can hide certain subtle errors. C is perfectly capable of implicitly casting the void* returned from malloc() into any other pointer type.
Related
I was trying to convert a list of integers into a compact string but I get a segmentation fault.
The code is the following:
int *factors = job_factorization(number, size);
char buffer[250] = { 0 };
for (int i = 0; i < *size; i++) {
sprintf( &buffer[i], "%d ", *factors);
factors++;
}
The job_factorization function returns the head of the list (it works, I have already tested it), and it sets the value pointed to by size to the actual size of the list (so the number of integers).
I cannot figure out what is wrong, does anyone have any idea?
Note these remarks:
sprintf( &buffer[i], "%d ", *factors); does not convert the number at the end of the previous conversion.
sprintf does not check for buffer overflow: if size is large enough, it will eventually write beyond the end of the buffer.
modifying factors is probably not a good idea as this pointer should be freed after use.
Here is an alternative:
int *factors = job_factorization(number, size);
char buffer[1024];
size_t pos = 0;
for (int i = 0; pos < sizeof buffer && i < *size; i++) {
pos += snprintf(buffer + pos, sizeof buffer - pos, "%d ", factors[i]);
}
You could also use 2 loops to compute the size needed for the conversion and allocate the space needed.
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);
}
}
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.
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.
int getbit(int * list, int n)
{
return (list[n / 32] >> (n % 32)) & 1;
}
void setbit(int * list, int n)
{
list[n / 32] |= 1 << (n % 32);
}
int main()
{
FILE * out;
int size = 99; //2000000000;
int root = sqrt(size);
int * list = malloc(size / 8.0); //(2*10^9)/8
memset(list, 0, sizeof list);
int i, j;
for (i = 2; i <= root; i++)
for (j = 2 * i; j < size; j += i)
setbit(list, j);
printf("i=%d j=%d 98=%d\n", i, j, getbit(list, 98));
out = fopen("output.txt", "w");
printf("i=%d j=%d 98=%d\n", i, j, getbit(list, 98));
/*for (i=2; i<size; i++)
if (!getbit(list, i))
fprintf(out, "%d\n", i);
fclose(out);*/
return 0;
}
Whenever I use the fopen() in between printf, the value of the third parameter changes from 1 to 0. If I comment out the line then the value is same. What might be the reason behind this?
You see undefined behavior: sizeof(list) is probably 4 or 8 bytes, depending on the architecture, so memset with zeros does not go past the forth byte. You are reading from the third 32-bit word, which came from malloc and has not been initialized by the memset yet. Moreover, you are allocating 12 bytes (size/8.0 gets converted to int; it never makes sense to pass a float or a double to malloc, because you cannot allocate fractional bytes) so accessing the 98-th bit goes past the allocated area.
You should fix these undefined behaviors: allocate enough memory by using
// count needs to be a multiple of sizeof(int)
// The math gets pretty ugly here, but it should work:
int count = sizeof(int)*(size+(8*sizeof(int))-1)/(8*sizeof(int));
int * list = malloc(count);
Then initialize the data to zero by using the proper size:
memset(list, 0, count);
You're writing in memory you do not own, that has an undefined behavior.
Firstly, you're allocating only 12 bytes here:
int* list = malloc(size / 8.0);
You should do this (just giving you the idea, I don't know how many bytes you really want to allocate..):
int* list = malloc((size / 8.0) * sizeof(*list));
Secondly, you are memsetting only 4 bytes (if you're on 32bits system) here:
memset(list, 0, sizeof list);
You should do this:
memset(list, 0, (size / 8.0) * sizeof(*list));
Finally, the only reason your call to fopen() changes things, is because fopen() allocates memory.
Good luck.