I'm trying to create a graph with 264346 positions. Would you know why calloc when it reaches 26,000 positions it stops generating memory addresses (ex: 89413216) and starts generating zeros (0) and then all the processes on my computer crash?
The calloc function should generate zeros but not at this position on my code.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#include <string.h>
#include <limits.h>
int maxV;
struct grafo {
int NumTotalVertices;
int NumVertices;
int NumArestas;
int **p;
};
typedef struct grafo MGrafo;
MGrafo* Aloca_grafo(int NVertices);
int main(){
MGrafo *MatrizGrafo;
MatrizGrafo = Aloca_grafo(264346);
return 0;
}
MGrafo* Aloca_grafo(int NVertices) {
int i, k;
MGrafo *Grafo ;
Grafo = (MGrafo*) malloc(sizeof(MGrafo));
Grafo->p = (int **) malloc(NVertices*sizeof(int*));
for(i=0; i<NVertices+1; i++){
Grafo->p[i] = (int*) calloc(NVertices,sizeof(int));// error at this point
//printf("%d - (%d)\n", i, Grafo->p[i]); // see impression
}
printf("%d - (%d)\n", i, Grafo->p[i]);
Grafo->NumTotalVertices = NVertices;
Grafo->NumArestas = 0;
Grafo->NumVertices = 0;
return Grafo;
}
You surely dont mean what you have in your code
Grafo = (MGrafo*)malloc(sizeof(MGrafo));
Grafo->p = (int**)malloc(NVertices * sizeof(int*)); <<<<=== 264000 int pointers
for (i = 0; i < NVertices + 1; i++) { <<<<< for each of those 264000 int pointers
Grafo->p[i] = (int*)calloc(NVertices, sizeof(int)); <<<<<=== allocate 264000 ints
I ran this on my machine
its fans turned on, meaning it was trying very very hard
after the inner loop got to only 32000 it had already allocated 33 gb of memory
I think you only need to allocate one set of integers, since I cant tell what you are trying to do it hard to know which to remove, but this is creating a 2d array 264000 by 264000 which is huge (~70billion = ~280gb of memory), surely you dont mean that
OK taking a comment from below, maybe you do mean it
If this is what you really want then you are going to need a very chunky computer and a lot of time.
Plus you are definitely going to have to test the return from those calloc and malloc calls to make sure that every alloc works.
A lot of the time you will see answers on SO saying 'check the return from malloc' but in fact most modern OS with modern hardware will rarely fail memory allocations. But here you are pushing the edge, test every one.
'Generating zeros' is how calloc tells you it failed.
https://linux.die.net/man/3/calloc
Return Value
The malloc() and calloc() functions return a pointer to the allocated memory that is suitably aligned for any kind of variable. On error, these functions return NULL. NULL may also be returned by a successful call to malloc() with a size of zero, or by a successful call to calloc() with nmemb or size equal to zero.
Related
I need to write in a variable allocated through a function. I found a lot of threads discussing this, such as Allocating a pointer by passing it through two functions and How to use realloc in a function in C, which helped me fixing some issues, but one remains and I can't find the cause.
Consider the following code:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
void foo(uint64_t** m)
{
*m = realloc(*m, sizeof(uint64_t) * 4);
*m[0] = (uint64_t)1;
//*m[1] = (uint64_t)2; // create a segfault and crash right here, not at the print later
}
int main()
{
uint64_t* memory = NULL;
foo(&memory);
for(int i = 0; i < 4; i++)
printf("%d = %ld\n", i, memory[i]);
return 0;
}
I send the address of memory to foo, which takes a double pointer as an argument so it can modify the variable. The realloc function need a size in bytes, so I make sure to ask for 4 * sizeof(uint64_t) to have enough space to write 4 64-bits int. (The realloc is needed, I don't need malloc).
I can then write in m[0] without issue. But if I write in m[1], the program crashes.
What did I do wrong here ?
We were shown this program in class yesterday and i have a question regarding it's output.
malloc.c:
#include <stdlib.h>
int *create_array(int);
int *create_array(int elements) {
int i,*x = (int *) malloc(elements*sizeof(int));
for(i=0;i < elements;i++) {
x[i] = i;
}
free(x);
return x;
}
int main(void) {
int j, *arr;
arr = create_array(5);
for(j=0;j<5;j++) {
printf("%d\n",arr[j]);
}
return 0;
}
Question(s):
When i run the program, i get this as output:
1627793032
1627793104
2
3
4
However, shouldn't the first 2 elements be 0 and 1 respectively? The values printed here seem like memory addresses to me, am i right? Also, is this due to some mistake causing undefined behavior?
After free(x);, the values pointed to by x are no longer valid. The memory can be reused for some other purpose, and meanwhile the memory allocation library can use the storage as it sees fit.
So, yes, it is a mistake resulting in undefined behaviour.
The real question is why do you even expect it to work? You free x, then you return a freed pointer which is nonsense.
What is happening is the following:
Inside the function you allocate 5 spaces, x points to the first
one's address.
You write 0, 1, 2, 3, 4 in these spaces.
You free x, so all the 5 spaces are not reserved anymore.
You exit the function, doing so the 2 next free memory spaces are
used, which happen to be the ones where you wrote 0 and 1.
You print the values contained in the 5 memory areas you've already
freed, where the ones in which you wrote 0 and 1 happen to have been
reused for something else; hence the weird numbers.
As a general rule, do not attempt to read areas of memory i've freed; even worse, do not try to WRITE there.
Accessing unallocated memory leads to undefined behaviour.
Also, you don't need to declare the function in a separate row if it's going to have nothing in between; plus you don't have to cast what's returned by malloc to the type; it's a void* that by default can hold anything you throw at it. What matters is your base variable type. See here
Corrected code:
#include <stdlib.h>
int *create_array(int elements) {
int i,*x = malloc(elements*sizeof(int));
for(i=0;i < elements;i++) {
x[i] = i;
}
return x;
}
int main(void) {
int j, *arr;
arr = create_array(5);
for(j=0;j<5;j++) {
printf("%d\n",arr[j]);
}
free(arr);
return 0;
}
we wrote a program that reads comma-separated integer-values into an array and tries processing them with a parallel structure.
By doing so, we found out that there is a fixed limitation for the maximum size of the dynamic array, which usually gets allocated dynamically by doubling the size. Yet for a dataset with more than 5000 values, we can't double it anymore.
I am a bit confused right now, since technically, we did everything the way other posts pointed out we should do (use realloc, don't use stack but heap instead).
Note that it works fine for any file with less or equal than 5000 values.
We also tried working with realloc, but to the same result.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// compile with gcc filename -lpthread -lm -Wall -Wextra -o test
int reader(int ** array, char * name) {
FILE *fp;
int data,row,col,count,inc;
int capacity=10;
char ch;
fp=fopen(name,"r");
row=col=count=0;
while(EOF!=(inc=fscanf(fp,"%d%c", &data, &ch)) && inc == 2){
if(capacity==count)
// this is the alternative with realloc we tried. Still the same issue.
//*array=malloc(sizeof(int)*(capacity*=2));
*array = realloc(*array, sizeof(int)*(capacity*=2));
(*array)[count++] = data;
//printf("%d ", data);
if(ch == '\n'){
break;
} else if(ch != ','){
fprintf(stderr, "format error of different separator(%c) of Row at %d \n", ch, row);
break;
}
}
// close file stream
fclose(fp);
//*array=malloc( sizeof(int)*count);
*array = realloc(*array, sizeof(int)*count);
return count;
}
int main(){
int cores = 8;
pthread_t p[cores];
int *array;
int i = 0;
array=malloc(sizeof(int)*10);
// read the file
int length = reader(&array, "data_2.txt");
// clean up and exit
free(array);
return 0;
}
EDIT: I included the realloc-command we tried and changed the values back to our original testing values (starting at 10). This didn't impact the result though, or rather still does not work. Thanks anyways for pointing out the errors! I also reduced the included code to the relevant part.
I can't really get my head around the fact that it should work this way, but doesn't, so it might just be a minor mistake we overlooked.
Thanks in advance.
New answer after question has been updated
The use of realloc is wrong. Always do realloc into a new pointer and check for NULL before overwriting the old pointer.
Like:
int* tmp = realloc(....);
if (!tmp)
{
// No more memory
// do error handling
....
}
*array = tmp;
Original answer (not fully valid after question has been updated)
You have some serious problems with the current code.
In main you have:
array=malloc(sizeof(int)*10); // This only allocates memory for 10 int
int length = reader(&array, "data_1.txt");
and in reader you have:
int capacity=5001;
So you assume that the array capacity is 5001 even though you only reserved memory for 10 to start with. So you end up writing outside the reserved array (i.e. undefined behavior).
A better approach could be to handle all allocation in the function (i.e. don't do any allocation in main). If you do that you shall initialize capacity to 0 and rewrite the way capacity grows.
Further, in reader you have:
if(capacity==count)
*array=malloc(sizeof(int)*(capacity*=2));
It is wrong to use malloc as you loose all data already in the array and leak memory as well. Use realloc instead.
Finally, you have:
*array=malloc( sizeof(int)*count);
Again this is wrong for the same reason as above. If you want to resize to the exact size (aka count) use realloc
if is it possible run-time bad pointer exception in C language?.
I am using below compiler.
Note : Microsoft Visual C++ Compiler
Sample Programs Below.
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <Windef.h>
typedef struct tagTest{
int i;
char *str;
} Test,
FAR *LPTest,
FAR **LLPTEST;
extern LLPTEST m;
int main()
{
int i;
LLPTEST m = NULL;
m = (LLPTEST)malloc(sizeof(LLPTEST));
// Here We Check m[0] memory allocated or not ?
// example: if(m[0]), or if(m[0]->i) any other idea. here m[0] is CXX0030 error expression cannot be evaluated.
/* allocate memory */
for(i=0; i<10; i++)
{
m[i] = (LPTest) malloc(sizeof(Test));
m[i]->i = i;
m[i]->str = (char*) malloc(10*sizeof(char));
m[i]->str = "Test";
}
return 0;
}
No. C doesn't support exceptions, so there's nothing to catch. What you're seeing isn't a "bad pointer exception," it's a memory access error -- there is no way to recover from it.
You have several problems in your code. Here's a list of some of them:
Don't cast the return of malloc
For m you allocate sizeof(LLPTEST) bytes, but you should really allocate sizeof(LPTest)
Continuing the previous point, you only allocate one pointer, so only m[0] is valid, all other indexes will cause you to write out of bounds. You should do e.g.
m = malloc(sizeof(LPTest) * 10);
This point is the cause of your problems, as it causes undefined behavior
You allocate memory for m[i]->str, but then you overwrite that pointer with a pointer to a string literal, thereby loosing the pointer to the allocated memory (i.e. you have a memory leak)
Continuing the previous point, because m[i]->str now points to a string literal, and not something you allocated yourself, you can not free this pointer
No error checking, remember that malloc can fail
If you don't know how many items you need to allocate for m beforehand, you can use realloc to reallocate with a larger size.
Some exceptions can catch MSVC is to extend the syntax.
#include <windows.h>
#include <stdio.h>
typedef struct tagTest{
int i;
char *str;
} Test;
int main(){
Test *m;
//m = malloc(sizeof(Test));//it can be avoided by examining whether NULL simply.
m = NULL;//malloc is unable to allocate memory
__try{
m->i = 0;//exception occurs
m->str = "Test";
}
__except(EXCEPTION_EXECUTE_HANDLER){
if(EXCEPTION_ACCESS_VIOLATION==GetExceptionCode())
puts("ACCESS VIOLATION");
puts("EXCEPTION OCCURRED");
}
}
I started to learn C recently. I use Code::Blocks with MinGW and Cygwin GCC.
I made a very simple prime sieve for Project Euler problem 10, which prints primes below a certain limit to stdout. It works fine until roughly 500000 as limit, but above that my minGW-compiled .exe crashes and the GCC-compiled one throws a "STATUS_STACK_OVERFLOW" exception.
I'm puzzled as to why, since the code is totally non-recursive, consisting of simple for loops.
#include <stdio.h>
#include <math.h>
#define LIMIT 550000
int main()
{
int sieve[LIMIT+1] = {0};
int i, n;
for (i = 2; i <= (int)floor(sqrt(LIMIT)); i++){
if (!sieve[i]){
printf("%d\n", i);
for (n = 2; n <= LIMIT/i; n++){
sieve[n*i] = 1;
}
}
}
for (i; i <= LIMIT; i++){
if (!sieve[i]){
printf("%d\n", i);
}
}
return 0;
}
Seems like you cannot allocate 550000 ints on the stack, allocate them dynamically instead.
int * sieve;
sieve = malloc(sizeof(int) * (LIMIT+1));
Your basic options are to store variables in data segment when your memory chunk is bigger than stack:
allocating memory for array in heap with malloc (as #Binyamin explained)
storing array in Data/BSS segments by declaring array as static int sieve[SIZE_MACRO]
All the memory in that program is allocated on the stack. When you increase the size of the array you increase the amount of space required on the stack. Eventually the method cannot be called as there isn't enough space on the stack to accomodate it.
Either experiement with mallocing the array (so it's allocated on the heap). Or learn how to tell the compiler to allocate a larger stack.