I am writing a ring buffer with C.
I am stuck on freeing the memory in the end.
The code compiles well, but the result shows circBuf_free function fails to free the allocated memory.
The relevant codes are:
#include <stdint.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> //memcpy
#define kNumPointsInMyBuffer 16
#define initialSize 10
typedef struct CircBuf_t //struct name CircBuf_t
{
uint32_t *buffer;
int head; // keep track the newest data
int tail; // keep track the oldest data
int maxLen; // maximum number of items in the buffer
}circBuf_t; //type name circBuf_t
// initialize the circular buffer
void circBuf_init(circBuf_t *c, const int maxLen, int sz)
{
c->buffer = malloc(maxLen * sz);
c->maxLen = maxLen;
if(c->buffer == NULL)
printf("Buffer initialization fails\n");
c->head = 0;
c->tail = 0;
}
/* free the memory, free c->buffer first, then c*/
void circBuf_free(circBuf_t *c){
free(c->buffer);
free(c);
}
int main(){
// initilize ring Buffer
const int maxLen = kNumPointsInMyBuffer;
// original src
int src[1024] = {};
int i =0;
for(i=0; i<1024; i++){
src[i] = i;
}
//data
uint32_t data[1024];
memcpy(data, src, 1024);
printf("\nThe size of the uint32_t data array is %lu\n", sizeof(data));
int sz = sizeof(*data);
circBuf_t *cb;
cb = malloc(sizeof(circBuf_t));
circBuf_init(cb, maxLen, sz);
assert(cb);
printf("cb's value is %p\n", cb);
circBuf_free(cb);
printf("cb's value is %p\n", cb);
assert(!cb);
return 0;
}
Result:
cb's value is 0x1266010
cb's value is 0x1266010
a.out: sample.c:73: main: Assertion `!cb' failed.
Aborted (core dumped)
The address of the pointer to the structure is the same.
Need help!
When you call free, the memory pointed to by the passed pointer is
freed, but the value of the pointer in the caller probably remains
unchanged, because C's pass-by-value semantics mean that called
functions never permanently change the values of their arguments. (See
also question 4.8.)
A pointer value which has been freed is, strictly speaking, invalid,
and any use of it, even if it is not dereferenced (i.e. even if the
use of it is a seemingly innocuous assignment or comparison), can
theoretically lead to trouble. (We can probably assume that as a
quality of implementation issue, most implementations will not go out
of their way to generate exceptions for innocuous uses of invalid
pointers, but the Standard is clear in saying that nothing is
guaranteed, and there are system architectures for which such
exceptions would be quite natural.)
When pointer variables (or fields within structures) are repeatedly
allocated and freed within a program, it is often useful to set them
to NULL immediately after freeing them, to explicitly record their
state.
Source :
http://c-faq.com/malloc/ptrafterfree.html
Related
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.
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 ?
I'm creating a source files containing buffer functionality that I want to use for my other library that I'm creating.
It is working correctly but I'm having trouble getting rid of the buffer structure that I'm creating in one of the functions. The following snippets should help illustrate my problem:
C header:
//dbuffer.h
...
typedef struct{
char *pStorage;
int *pPosition;
int next_position;
int number_of_strings;
int total_size;
}DBUFF;
...
C source:
//dbuffer.c
...
DBUFF* dbuffer_init(char *init_pArray)
{
//Find out how many elements the array contains
int size = sizeof_pArray(init_pArray);
//Initialize buffer structure
DBUFF *buffer = malloc(sizeof(DBUFF));
//Initialize the storage
buffer->pStorage = malloc( (sizeof(char)) * (size) );
strncpy( &(buffer->pStorage)[0] , &init_pArray[0] , size);
buffer->number_of_strings = 1;
buffer->total_size = size;
buffer->next_position = size; //size is the next position because array allocates elements from 0 to (size-1)
//Initialize the position tracker which keeps record of starting position for each string
buffer->pPosition = malloc(sizeof(int) * buffer->number_of_strings );
*(buffer->pPosition + (buffer->number_of_strings -1) ) = 0;
return buffer;
}
void dbuffer_destroy(DBUFF *buffer)
{
free(buffer->pStorage);
free(buffer);
}
...
Main:
#include <stdio.h>
#include <stdlib.h>
#include "dbuffer.h"
int main(int argc, char** argv)
{
DBUFF *buff;
buff = dbuffer_init("Bring the action");
dbuffer_add(buff, "Bring the apostles");
printf("BUFFER CONTENTS: ");
dbuffer_print(buff);
dbuffer_destroy(buff);
// Looks like it has been succesfully freed because output is garbage
printf("%s\n", buff->pStorage);
//Why am I still able to access struct contents after the pointer has been freed ?
printf("buff total size: %d\n", buff->total_size);
return (EXIT_SUCCESS);
}
Output:
BUFFER CONTENTS: Bring the action/0Bring the apostles/0
��/�
buff total size: 36
RUN SUCCESSFUL (total time: 94ms)
Question:
Why am I still able to access struct contents using the line below after the pointer to the struct has been freed ?
printf("buff total size: %d\n", buff->total_size);
Once you've called free() on the allocated pointer, attempt to make use of the pointer invokes undefined behavior. You should not be doing that.
To quote C11 standard, chapter §7.22.3.4, free() function
The free() function causes the space pointed to by ptr to be deallocated, that is, made
available for further allocation. [..]
It never say's anything about a cleanup, which you might be (wrongly) expecting.
Just to add clarity, calling free() does not always actually free up the allocated physical memory. It just enables that pointer (memory space) to be allocated again (returning the same pointer, for example) for successive calls to malloc() and family. After calling free(), that pointer is not supposed to be used from your program anymore but C standard does not guarantee of a cleanup of the allocated memory.
If any attempt is made to read memory that has been freed can crash your program. Or they might not. As far as the language is concerned, its undefined behaviour.
Your compiler won't warn you about it(or stop you from accessing it). But clearly don't do this after calling free -
printf("buff total size: %d\n", buff->total_size);
As a good practice you can set the freed pointer to NULL .
free() call will just mark the memory in heap as available for use. So you still have the pointer pointing to this memory location but it's not available anymore for you. Thus, the next call to malloc() is likely to assign this memory to the new reservation.
To void this situations normally once you free() the memory allocated to a pointer you should set it to NULL. De-referencing NULL is UB also but at least when debugging you can see tha pointer should not be used because it's not pointing to a valid memory address.
[too long for a comment]
To allow your "destructor" to set the pointer passed to NULL modify your code like this:
void dbuffer_destroy(DBUFF ** buffer)
{
if ((NULL == buffer) || (NULL == *buffer))
{
return;
}
free((*buffer)->pPosition);
free((*buffer)->pStorage);
free(*buffer);
*buffer = NULL;
}
and call it like this:
...
dbuffer_destroy(&buff);
...
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");
}
}
This question already has answers here:
Determine size of dynamically allocated memory in C
(15 answers)
Closed 3 years ago.
I have faced some problem in this case can you please your ideas.
main()
{
char *p=NULL;
p=(char *)malloc(2000 * sizeof(char));
printf("size of p = %d\n",sizeof (p));
}
In this program Its print the 4 that (char *) value,but i need how many bytes allocated for
that.
You could also implement a wrapper for malloc and free to add tags (like allocated size and other meta information) before the pointer returned by malloc. This is in fact the method that a c++ compiler tags objects with references to virtual classes.
Here is one working example:
#include <stdlib.h>
#include <stdio.h>
void * my_malloc(size_t s)
{
size_t * ret = malloc(sizeof(size_t) + s);
*ret = s;
return &ret[1];
}
void my_free(void * ptr)
{
free( (size_t*)ptr - 1);
}
size_t allocated_size(void * ptr)
{
return ((size_t*)ptr)[-1];
}
int main(int argc, const char ** argv) {
int * array = my_malloc(sizeof(int) * 3);
printf("%u\n", allocated_size(array));
my_free(array);
return 0;
}
The advantage of this method over a structure with size and pointer
struct pointer
{
size_t size;
void *p;
};
is that you only need to replace the malloc and free calls. All other pointer operations require no refactoring.
There is no portable way but for windows:
#include <stdio.h>
#include <malloc.h>
#if defined( _MSC_VER ) || defined( __int64 ) /* for VisualC++ or MinGW/gcc */
#define howmanybytes(ptr) ((unsigned long)_msize(ptr))
#else
#error no known way
#endif
int main()
{
char *x=malloc(1234);
printf( "%lu", howmanybytes(x) );
return 0;
}
Although it may be possible that some libraries allows you to determine the size of an allocated buffer, it wouldn't be a standard C function and you should be looking at your library's own documentations for this.
However, if there are many places that you need to know the size of your allocated memory, the cleanest way you could do it is to keep the size next to the pointer. That is:
struct pointer
{
size_t size;
void *p;
};
Then every time you malloc the pointer, you write down the size in the size field also. The problem with this method however is that you have to cast the pointer every time you use it. If you were in C++, I would have suggested using template classes. However, in this case also it's not hard, just create as many structs as the types you have. So for example
struct charPtr
{
size_t size;
char *p;
};
struct intPtr
{
size_t size;
int *p;
};
struct objectPtr
{
size_t size;
struct object *p;
};
Given similar names, once you define the pointer, you don't need extra effort (such as casting) to access the array. An example of usage is:
struct intPtr array;
array.p = malloc(1000 * sizeof *array.p);
array.size = array.p?1000:0;
...
for (i = 0; i < array.size; ++i)
printf("%s%d", i?" ":"", array.p[i]);
printf("\n");
It is impossible to know how much memory was allocated by just the pointer. doing sizeof (p) will get the size of the pointer variable p which it takes at compile time, and which is the size of the pointer. That is, the memory the pointer variable takes to store the pointer variable p. Inside p the starting address of the memory block is stored.
Once you allocate some memory with malloc it will return the starting address of the memory block, but the end of the block cannot be found from it, as there is no terminator for a block. You define the end of the block therefore you need to identify it by any means, so store it somewhere. Therefore you need to preserve the block length somewhere to know where the block which is pointed to by p ends.
Note: Although the memory allocation structure keeps track of allocated and unallocated blocks, therefore we can know the allocated memory block length from these structures, but these structures are not available to be used by the users, unless any library function provides them. Therefore a code using such feature is not portable (pointed by #Rudy Velthuis) . Therefore it is the best to keep track of the structure yourself.
You need to keep track of it in a variable if you want to know it for later:
char *p = NULL;
int sizeofp = 2000*sizeof(char);
p = (char *)malloc(sizeofp);
printf("size of p = %d\n",sizeofp);
You cannot use the sizeof in this case, since p is a pointer, not an array, but since you allocate it, you already know:
main()
{
size_t arr_size = 2000;
char *p=NULL;
p=malloc(arr_size * sizeof(char));
printf("size of p = %d\n",arr_size);
}
Edit - If the malloc fails to allocate the size you wanted, it won't give you a pointer to a smaller buffer, but it will return NULL.