I am trying to create a function that allocates memory of a certain specified size. In the main, I create the pointer and then send the pointer and the size to the function for memory to be allocated. For some reason it causes all sorts of problems. My program works smoothly if I use the malloc in the main, but not through the function.
int main(void){
int * pointer;
int array_size = SIZE;
...
allocate_memory(&pointer,array_size);
...
free(pointer);
}
allocate_memory(int *pointer,int size){
*pointer = (int *)malloc(size*sizeof(int));
if(!(*pointer)){
printf("Memory allocation fail!");
exit(0);
}
The problem now is that it gives me an error when I try to free the memory.
I would appreciate it if the solution will come with a short explanation. I am starting to be very confused about how these pointers and castings are working.
Thanks in advance!
There were many errors in your program which I am pointing out:
You need to #define the macro SIZE as otherwise the program just won't know what it is.
It's better to declare a prototype of the function allocate_memory() so that any discrepancy in type of arguments or return type is detected
You had passed &pointer as an argument to allocate_array() in main().For this it is necessary to define the function as allocate_memory(int **pointer,int size) instead of allocate_memory(int *pointer,int size) which you have done.
if(*pointer==NULL) implements the condition in a much simpler way and serves just the same purpose.
Use exit(1) for unsuccessful termination as exit(0) is used to denote successful termination.
Never ignore warnings.It's not a good practice.
Here's the corrected code.It compiles well without warnings and does the job (memory allocation) as intended.
#include<stdio.h>
#include<stdlib.h>
#define SIZE 30
void allocate_memory(int**,int);
int main(void){
int * pointer;
int array_size = SIZE;
allocate_memory(&pointer,array_size);
free(pointer);
}
void allocate_memory(int **pointer,int size)
{
*pointer = malloc(size*sizeof(int));
if(*pointer==NULL)
{
printf("Memory allocation fail!");
exit(1);
}
else
printf("\nMemory allocation successful");
}
Related
If we were to use malloc() in main(), we could free() that dynamic memory allocation in main().
However, if we use malloc() in a different function
and we use that function in main(), where should we call free() to release the memory allocated in that function?
I.e., in the following source code:
#include <stdio.h>
#include <stdlib.h>
int * memory_allocate_function(int);
int main(void) {
int n=5; //length of array, 5 for example.
int *my_array;
my_array = memory_allocate_function(n);
return 0;
}
int * memory_allocate_function(int n) {
int i;
int *array;
array=(int *)malloc(n * sizeof(int));
if(array == NULL) {
printf("can not allocate memory.");
return NULL;
}
// I think i can't use "free(array);" in here.
// Because I need that array in main().
return array;
}
Is this the best way to do this?
Well after you are done working with it - free the dynamically allocated memory. But design wise - you can call the free in other function also to manage it properly. It really depends. There is no hard rule for that.
For example here you should return that pointer to allocated memory and then after using it in main you can free it in main().
So the structure would be something like
int* memory_allocate_function(int n)
{
int i;
int *array;
array = malloc(n*sizeof(int));
if(array == NULL)
{
printf("can not allocate memory.");
exit(0);
}
return array;
}
Then in main()
int main(void)
{
int n=5; //length of array, 5 for example.
int *arr = memory_allocate_function(n);
// work with arr
free(arr);
return 0;
}
But yes name the function properly - if you are going to use the name memory_allocate_function function then do that only - not any other major logic should be there. This helps create a good readable code.
Note one thing - here when you called the function and then you exited the function the only local variable that contains address of it, it's storage duration ended and you can never then access the memory you allocated. This is a case of memory leak. If you are determined that you won't return the pointer to memory from the function - then work with it (in the same function or different) and then free it (Before the scope of the function ends - notice not mentioning about where you would free it, you can do it in the same function and other function also).
I can't help mentioning few things:- 1) Dont cast the return value of malloc. 2) Check the return value of malloc - in case it is NULL you would like to handle it separately. 3) The recommended signature of main() is int main(void)
Memory should be freed when it's no longer needed.
Since the array would no longer be accessible after memory_allocate_function exits (since the array isn't returned or otherwise made accessible to the outside), it should be freed before memory_allocate_function exits.
void memory_allocate_function(int n){
int i;
int *array;
array = malloc(n*sizeof(int));
if (array == NULL) {
fprintf(stderr, "Out of memory.");
exit(1);
}
// ... use the array ...
free(array);
}
If you need to malloc memory in one function and free in another, you have to somehow carefully pass the pointer to that malloced memory from the point of malloc to the point where you want to free it.
This is your responsibility to preserve the pointer value and hand it from one function to another until it reaches the point of free. If you lose that value along the way, you'll have a memory leak. A memory leak is what you have now, since you are not passing that local array pointer anywhere.
There's no "one true way" to do it, since it depends on your specific intent. For example, you can return that pointer from memory_allocate_function, receive it main and eventually free it there
int *memory_allocate_function(int);
int main()
{
int n = 5;
int *arr = memory_allocate_function(n);
...
free(arr);
return 0;
}
int *memory_allocate_function(int n)
{
int *array = malloc(n * sizeof *array);
...
return array;
}
There is program for reading from file and return a struct.
struct ion_bin
{
int freq;
long height;
int amplitude;
};
//Dynamic auto allocating array
typedef struct {
struct ion_bin *array;
size_t used;
size_t size;
} Ionogram;
void freeArray(Ionogram *a); //free memory
void insertArray(Ionogram *a, struct ion_bin element); //realloc memory
void initArray(Ionogram *a, size_t initialSize); //malloc memory
Ionogram* read(int argn, char* argv[])
{
FILE* stream;
Ionogram ionogramObj;
//fill ionogram from file by initArray and insertArray
//.....
return &ionogramObj;
}
int main(int argn, char* argv[])
{
Ionogram* r = read(argn, argv);
fprintf(stderr,"Array size: %d Used %d\n",r->size, r->used); //SEGMENTATION FAULT ERROR
//int second = (*(r->array + 2)).amplitude; //YET SEGMENTATION FAULT ERROR TOO
//fprintf(stderr, "%d", second);
return 0;
}
This program compile successfully, but in runtime and debug fires segmentation fault error (SIGSEGV) by attempt getting fields of returned struct (in main method) How to fix this error?
You make a beginners mistake, and return a pointer to a local variable. You got to remember that local variables goes out of scope once the function returns, and the pointers to it will then become invalid. Dereferencing this invalid pointer leads to undefined behavior.
Two possible solutions:
Actually return a structure, by value, and not a pointer.
Allocate memory for the structure using malloc, and return a pointer to this dynamically allocated memory.
Method one works well for smaller structures, like yours, but become inefficient for larger structures as the whole structure must be copied. (It's a shallow copy though, not a deep copy. So if you have pointers in the structure only the pointers are copied and not what they point to.)
You are returning a pointer to a variable that goes out of scope at the end of the function.
Ionogram ionogramObj;
return &ionogramObj;
That's undefined behaviour in C.
As an alternative, malloc the memory for your structure in the function and return the pointer to that. Don't forget to free the pointer at some point.
In your code, ionogramObj variable is local to the function read(). Once the function finishes the execution, there is no existence of ionogramObj, so, essentially the returned address becomes invalid in the caller (main()).
Accessing invalid address (pointer) invokes undefined behaviour. Segmentation fault is one of the side effect of UB.
To avoid this, you'll need to return an address which has a lifetime bigger than that of the called function . With the help of a pointer and dynamic memory allocation, you can achieve this.
See a pseudo code
Ionogram* read(int argn, char* argv[])
{
FILE* stream = NULL;
Ionogram *ionogramObj = NULL; //take a pointer
ionogramObj = malloc(sizeof(*ionogramObj)); //allocate memory dynamically
if (!ionogramObj) //don't forget to check for success
//some error message, return or exit, maybe?
else
//do normal operation
//fill ionogram from file by initArray and insertArray
//.....
return ionogramObj; //return the pointer
}
Also, dynamically allocated memory needs to be free()d to avoid memory leak. Once you're done using the return value, you can call free() with the returned pointer in the caller (main()).
I'm working on a C project (assignment for school). One of the demands is that in case of malloc() failure, the program must free() all allocated memory and exit().
Consider a case where function A() constructs a linked-list and in each iteration it calls to another function, B(). Now, if a malloc failure occured at B(), it must free() the memory it allocated but function A() should do that as well.
Things are getting quite complicated when you have a tree of function calls larger than two.
In my previous project I used a flag to notify a malloc() failure - if a function uses another function which may use malloc(), it has to check the flag right after. It worked, but code got kinda messy.
Is there a neat solution for this problem?
Of course, with "real" applications all memory is de-allocated by the OS, but I guess this demand is pedagogical..
I think the easiest approach is to create a custom allocator (as somebody already noted in a deleted post) to keep track of all your allocations, then do a custom deallocator, use these for all your heap memory needs.
if a malloc fails you have the list of previously allocated blocks at easy reach.
e.g.
(you need to redo this cause it is not effective and should be optimized but shows the principle and only ocular compilation)
typedef struct
{
void* pMemory; /* for the allocated memory */
size_t size; /* for better debugging */
} MemoryBlock;
#define MAXBLOCKS 1000
MemoryBlock myheap[MAXBLOCKS]; // global so zero:ed
static int block = 0;
void* myalloc(size_t size)
{
static int block = 0;
// you should check vs MAXBLOCKS
myheap[block].pMemory = malloc(size);
myheap[block].size = size;
// check if it failed.
if ( myheap[block].pMemory == NULL )
{
for (int i = 0; i < block; ++i)
{
myfree(myheap[i].pMemory);
}
fprintf( stderr, "out of memory\n");
exit(EXIT_FAILURE);
}
else
{
return myheap[block++].pMemory;
}
}
void myfree(void* p)
{
for (int i = 0; i < block; ++i)
{
if ( p == myheap[i].pMemory )
{
free(myheap[i].pMemory);
myheap[i].pMemory = NULL;
return;
}
}
}
Yes. The best (and conventional) way is to initialize every pointer value to zero. Then set it during the malloc() assignment. Ex: myPtr = malloc( 10 );
It will be zero in case of failure, and you check that. And finally, when you go about freeing, you always check the pointer value before calling free():
if ( myPtr != 0 )
free( myPtr );
There is no need for an extra flag.
Are you having issue checking for errors or handling them? If you want info on catching them, use donjuedo's suggestion.
For ideas on freeing memory in the event of error, try one of these two methods:
1) For a uni-directional linked-list, keep a special pointer that points to the head of the list. In your cascading free function, start at the head, capture the next-pointer in a temp variable, free the head, move to the next structure in the list using the temp-pointer, and repeat the process until the next-pointer == 0.
2) For a bi-directional linked-list (my preference) you don't need to keep a special pointer to the head of the list. Assuming you are still at the tail, just capture the previous-pointer into a temp variable, free the tail, move back using the temp-pointer, and repeat the process until the previous-pointer == 0
You could look into the atexit() function, to register code that will be executed when the program terminates. Such code can then check if there is anything that needs to be free()d.
Note that atexit() has no way to unregister. So you need to make sure that you register each cleanup function only once, and that it does the right thing when there is nothing to clean up.
#include <stdlib.h>
#include <stdio.h>
int *ptr1;
char *ptr2;
int clean1_registered, clean2_registered;
void clean1(void)
{
printf("clean1 called\n");
if (ptr1) {
free(ptr1);
ptr1 = NULL;
}
}
void clean2(void)
{
printf("clean2 called\n");
if (ptr2) {
free(ptr2);
ptr2 = NULL;
}
}
void B(void)
{
ptr2 = malloc(100);
if (!clean2_registered) {
atexit(clean2);
}
}
void A(void)
{
ptr1 = malloc(100 * sizeof(int));
if (!clean1_registered) {
atexit(clean1);
}
B();
}
int main(int argc, char **argv)
{
A();
}
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");
}
}
When I execute this code, I'm receiving a "segmentation error (core dumbed)".
#include <pthread.h>
#include <stdio.h>
void function(char *oz){
char *y;
y = (char*)oz;
**y="asd";
return NULL;
}
int main(){
char *oz="oz\n";
pthread_t thread1;
if(pthread_create(&thread1,NULL,function,(void *)oz)){
fprintf(stderr, "Error creating thread\n");
return 1;
}
if(pthread_join(thread1,NULL)){
fprintf(stderr, "Error joining thread\n");
return 2;
}
printf("%s",oz);
return 0;
}
First you need to decide, how you want to manage the memory: is the memory allocated by caller, or inside the thread function.
If the memory is allocated by caller, then the thread function will look like:
void *function(void *arg)
{
char *p = arg;
strcpy(p, "abc"); // p points to memory area allocated by thread creator
return NULL;
}
Usage:
char data[10] = "oz"; // allocate 10 bytes and initialize them with 'oz'
...
pthread_create(&thread1,NULL,function,data);
If the memory is allocated inside the thread function, then you need to pass pointer-to-pointer:
void *function(void *arg)
{
char **p = (char**)arg;
*p = strdup("abc"); // equivalent of malloc + strcpy
return NULL;
}
Usage:
char *data = "oz"; // data can point even to read-only area
...
pthread_create(&thread1,NULL,function,&data); // pass pointer to variable
...
free(data); // after data is not needed - free memory-
Your compiler might be warning you about some of these problems. Don't ignore compiler warnings! Warnings are the way your compiler tells you "Hold on! I don't quite understand this bit of code... Please put it in a language I understand!". Which book are you reading? I see other problems, which I won't mention in this question, arising from this approach. It's not safe to learn C by "trial and error", or by "misguided example" (eg. copying/pasting and modifying). You should be reading a book written by a professor who teaches programming for a living, and has a bloody good reputation for doing so. Please answer this question before reading any further.
pthread_create expects a function pointer that indicates a function with a signature like this:
void *function(void *argument);
The function pointer you're giving it will be converted to a function pointer that assumes that signature. pthread_create will then try to use that function pointer, the only way it knows how... This is undefined behaviour. ... and besides, as indicated by #AdamRosenfield, you can't return values from a function that returns void. This ought to be causing your compiler to spew errors and warnings at you. Your function should look like:
void *function(void *oz) {
/* ... */
}
In the block comment is another series of lies in your question. Your code doesn't segfault, because it doesn't compile. y is a char *... *y is a char... **y is a compiler error. I would assume that you only meant to dereference it once, but then assigning "asd" to a char makes no sense, either, so I must assume you meant to declare y as char **y;. You seem to be using typecasts superfluously. Learn about them before you use them, so that you don't misuse them or use them in places where you don't need to (such as trying to convert a char * to a char *... wtf?).
void *function(void *oz) {
char **y = oz;
*y = "asd";
}
Hence, you should probably be passing pthread_open a char ** value, too. It makes no sense to pass a char * value and then treat it as though it's a char ** value, right? There's no need to cast any pointer to object to a void *; That conversion is one of the automatic ones.
if (pthread_create(&thread1, NULL, function, &oz)){
fprintf(stderr, "Error creating thread\n");
return 1;
}