Apologies for the really bad question - I wasn't really sure how to word it.
I'm executing a piece of code where I'm trying to use a dynamic array. It is segfault-ing at this line:
void myFunction(....) {
// other code up here
Stack *s = stack_new(); //segfault here
}
The relevant header file for my struct is:
typedef struct {
void **A;
int size;
int top; // the index of the current top of the stack
} Stack;
and the function stack_new() is:
Stack
*stack_new() {
Stack *s;
s->size = 1;
s->top = -1;
s->A = (void **)malloc(s->size);
return s;
}
I think I've included everything that is relevant, but please let me know if you need more code.
I think that the problem is with the way I'm using malloc, but have had a search online and have tried a few different options and am still getting the segfault. Is anyone able to offer some insight?
Thank you heaps
This is your problem:
Stack *s;
s->size = 1;
you're not actually allocating a Stack. s is uninitialized and points to an arbitrary location in the memory. s->size will obviously fail then.
Try:
Stack *s = malloc(sizeof(*s));
if (s == NULL)
{
fprintf(stderr, "Memory allocation error\n");
exit(1);
}
s->size = 1;
Note: you should also check if s->A is NULL. If so, return an error code (such as NULL) and before that remember to free the Stack you allocated, or alternatively print an error message and exit the program. If you exit the program, the operating system will reclaim all memory used so no need to do it explicitly then.
Another note: when doing
s->size = 1;
s->top = -1;
s->A = (void **)malloc(s->size);
...you allocate 1 byte of memory even though you should be allocating sizeof(void*) bytes of memory. Try doing
s->A = (void **)malloc(s->size*sizeof(void*));
instead.
Here's your first problem:
Stack *s;
s->size = 1;
What do you actually expect the value of s is at this point? It could be literally anything. You can't set a field of a struct if the struct itself isn't already allocated.
Try:
Stack *s = malloc(sizeof(*s));
if(!s){
//... error checking / exiting ..
}
and then everything else you were doing.
You are accessing a not initialized pointer!
Stack
*stack_new() {
Stack *s = std::nullptr; // initialize this pointer with nullptr
// and then you will see later (one line
// beyond) that you will try to access a
// null pointer
s->size = 1; // the problem occurs here!!
// you are accessing a pointer, for which has never
// been allocated any memory
s->top = -1;
s->A = (void **)malloc(s->size);
return s;
}
You will have to use "malloc" to allocate some memory for this pointer.
sth. like this is missing between those two lines, I commented:
Stack
*stack_new() {
Stack *s = (Stack*)malloc(sizeof(Stack));
s->size = 1;
s->top = -1;
s->A = (void **)malloc(s->size);
return s;
}
Related
int listLength(struct node *r) {
int *len = (int *)malloc(sizeof(int));
if(!r) {
free(len);
return *len;
}
while(r) {
r = r->next;
*len += 1;
}
free(len)
return *len;
}
I wrote this function to calculate the length of the linked list. I am still learning pointers by playing with them. I understand I could have used a simple len variable in the function,but I want to learn the basics of dynamic memory allocation. Why the length is always 0 after even though list has few elements? When should free() be called ?
You cannot use the memory once you free() it. So,
free(len);
return *len;
is wrong and undefined behavior.
Instead, you can use a local variable to hold the value and return it.
Also, FWIW,
int *len = (int *)malloc(sizeof(int));
if(!r) {
free(len);
return *len;
}
in the above code, you're trying to use the *len as return value, which is uninitialized. Even without the free()ing, you should not do that.
Also, you should always check for the success of malloc() vefore using the returned pointer.
A modified version:
int listLength(struct node *r) {
int *lenp = malloc(sizeof(int));
int len = 0;
if (!lenp) //check malloc success
exit(-1);
*lenp = len;
if(!r) {
free(lenp);
return len;
}
while(r) {
r = r->next;
*lenp += 1;
}
len = *lenp;
free(lenp);
return len;
}
EDIT:
In your case, there is no need to use dynamic memory allocation at all. AS suggested by Mr. # Barak Manos and Mr. # WhozCraig, you should use dynamic memory allocation only when the memory requirement is not known at compile time. Otherwise, in general, static (compile time) memory allocation should do just fine.
A better and cleaner approach to your code,
int listLength(struct node *r) {
int len = 0;
while(r) {
r = r->next;
len += 1;
}
return len;
}
In general: after you have free()'d a memory block, you must never access it anymore. Just think of have given that block away. It is not yours anymore!
From this follow that you have to free a block only if you don't want to access it anymore. That's a fundamental rule; never ever break it.
For this example, as others have stated, there is actually no need to use dynamic memory at all.
Oh, and: you really should never cast the result of malloc! It returns void * wich can be assigned to any other pointer type. Read the standard, section 6.5.16.1 .
I'm take some errors trying free memory. A post all my code below.
I'm using ubuntu and I compile my code with gcc. But when I try execute my code I take an error while trying free memory.
I put comments on my code to explain my doubt. I'm working with stack structre.
How Do I free memory without take error to turn free memory for char?
If I whoud not free the memory allocated for the data (a char), and only to free the memory for the element (which contains the char data), which happens with memory allocated to the data? is it free?
ERROR
{
*** glibc detected *** ./pilha: free(): invalid next size (fast): 0x08b86018 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x74f82)[0xb7637f82]
./pilha[0x80485ba]
./pilha[0x804864c]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb75dc4d3]
./pilha[0x8048411]
======= Memory map: ========
}
CODE
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct Stack_element{
char *data;
struct Stack_element *next;
}Element;
typedef struct Position{
Element *top;
int size;
}stack;
void start(stack *aux){
aux->top = NULL;
aux->size = 0;
}
int push(stack *aux, char value){
Element *new_element;
if ((new_element = (Element*) malloc(sizeof(Element))) == NULL)
return -1; //an error occur
if ((new_element->data = (char*) malloc(sizeof(char))) == NULL)
return -1; //an error occur
strcpy(new_element->data, &value);
new_element->next = aux->top;
aux->top = new_element;
aux->size++;
}
int empty(stack *aux){
if ((aux->size) == 0){
return -1;
}
return 0;
}
char pop(stack *aux){
Element *element;
char value='0';
if (empty(aux)){
return '1';
}
element = aux->top;
aux->top = aux->top->next;
/*
To observe the line below. When a element exist in the stack and
I try remove this element, first I free the data in that node (element)
so I turn free memory allocated for the element.
If I didn't free data memory allocated before (in push fuction), I
don't get any error. But the memory allocated for the data, what happens?
Does is it continues allocated?
*/
value = *(element->data);
free(element->data);//THE ERROR OCCURS HERE, IN THIS LINE
free(element);//Just after free the data element memory, I also free the element's memory
aux->size--;
return value;
}
int main(){
stack p;
char value;
start(&p);
//no error occurs. there isn't any element at this moment.
printf("%c\n",pop(&p));
//valor = 't';
if (push(&p, 't')){
printf("Add a char\n");
}
pop(&p);//the error occurrs now, after insert an new element in the stack
printf("The End.");
}
In your code,
strcpy(new_element->data, &value);
is not correct. You have allocated memory for only one char which is not having space for null terminator. Instead you should use
*(new_element->data) = value;
Otherwise, with the improper usage of strcpy(), you'e messing up the allocated memory by making memory overrung which causes undefined behaviour.
At least this statement in function push is invalid
strcpy(new_element->data, &value);
You should write
if ( ( new_element->data = (char*) malloc( 2 * sizeof(char))) == NULL)
{
free( new_element );
return -1; //an error occur
}
new_element->data[0] = value;
new_element->data[1] = '\0';
Or
if ( ( new_element->data = (char*) malloc( sizeof(char))) == NULL)
{
free( new_element );
return -1; //an error occur
}
*new_element->data = value;
Function empty looks strange. Usually -1 is returned from a function when some error occurred. As for the function empty then neither error can occur. So it is better when the function returns 1 if the stack is empty. I would write it like
int empty( stack *aux )
{
return aux->size == 0;
}
Also it is not clear why function pop returns character '1' when the stack is empty. It would be better if it returns simply '\0'. So instead of
char pop(stack *aux){
Element *element;
char value='0';
if (empty(aux)){
return '1';
}
//,,
I would write
char pop(stack *aux){
if ( empty( aux ) ) return '\0';
Element *element;
//,,
My app is use in stlinux (sh4) and unfortunately valgrind does not support sh4 cpu.
since I saw memory leak with my app, I had used mtrace, and it confirmed that some memory is not free. The problem is, variable of malloc used in the return, therefore I do not have any idea, how could I free it (since if it would be free, then returning in the functions is meaningless)?
I had written cs_malloc (put bellow code from oscam-simple.c in above link), mtrace log says, that in line:
*tmp = malloc (size);
memory is not free
/* This function encapsulates malloc. It automatically adds an error message to the log if it failed and calls cs_exit(quiterror) if quiterror > -1.
result will be automatically filled with the new memory position or NULL on failure. */
void *cs_malloc(void *result, size_t size, int32_t quiterror){
void **tmp = result;
*tmp = malloc (size);
if(*tmp == NULL){
cs_log("Couldn't allocate memory (errno=%d %s)!", errno, strerror(errno));
if(quiterror > -1) cs_exit(quiterror);
} else {
memset(*tmp, 0, size);
}
return *tmp;
}
And then for malloc, I call it, like this:
// create the AES key entry for the linked list
if(!cs_malloc(&new_entry, sizeof(AES_ENTRY), -1)) return;
Please take a look at these 3 functions (which malloc is not free , and as other users said, valgrind claim that these codes cause memory leaks module-datastruct-llist.c
The memory leaks cause by 3 different parts:
in below codes "new" would never free , but since it use in return of that function, I don't have idea, how could I free it:
LL_NODE* ll_append_nolock(LLIST *l, void *obj)
{
if (l && obj) {
LL_NODE *new;
if(!cs_malloc(&new,sizeof(LL_NODE), -1)) return NULL;
new->obj = obj;
if (l->last)
l->last->nxt = new;
else
l->initial = new;
l->last = new;
l->count++;
return new;
}
}
also "l" use in below function, again since it use in return function, I have no idea how to free it. :
LLIST *ll_create()
{
LLIST *l = cs_malloc(&l, sizeof(LLIST), 0);
pthread_mutex_init(&l->lock, NULL);
return l;
}
same story with new :
LL_NODE *ll_prepend(LLIST *l, void *obj)
{
if (l && obj) {
LL_NODE *new;
if(!cs_malloc(&new,sizeof(LL_NODE), -1)) return NULL;
new->obj = obj;
ll_lock(l);
new->nxt = l->initial;
l->initial = new;
if (!l->last)
l->last = l->initial;
l->count++;
ll_unlock(l);
return new;
}
return NULL;
}
For more functions you could see module-datastruct-llist.c
Would highly appreciate, if any expert tell me, how could I fix that memory leak (if you feel, cs_malloc should be rewritten, or need to add new function, please write the source code you are meaning.
The most common implementations of malloc use heap memory, which is global, so it's very common to have storage allocated in one place passed around between a number of functions before it is finally freed.
Now, there are for instance calls to ll_append_nolock where you ignore the malloced return. I.e.
ll_append_nolock(it->l, obj);
so to avoid a leak you need to do what you do in other places, i.e let the calling function receive the allocated memory into a pointer:
LL_NODE *n = ll_append_nolock(l, obj);
/* do stuff with "n", which points to memory allocated under the name of "new" */
free(n);
And when you're through with n (which as noted above points to the storage allocted under the name "new", that is: same memory, different names), you free it.
HTH.
In your function cs_malloc the first parameter is result however you never assign to it in the function cs_malloc.
Later you use cs_malloc like this
if(!cs_malloc(&new,sizeof(LL_NODE), -1)) return NULL;
new->obj = obj;
which will not work since since "new" is left uninitialized
you should either assign to result in your cs_malloc or just return the block in cs_malloc, if you fail to allocate just return NULL instead.
e.g.
void *cs_malloc(size_t size, int32_t quiterror)
{
void* tmp = calloc(1,size);
if(tmp == NULL)
{
cs_log("Couldn't allocate memory (errno=%d %s)!", errno, strerror(errno));
if(quiterror > -1) cs_exit(quiterror);
}
return tmp;
}
and
if (new = cs_malloc(sizeof(LL_NODE),-1))
{
new->obj = obj;
}
else
{
return NULL;
}
#Anders
Thanks for reply , i would take consideration your note ,an would change it as u described to see memory leaks how it's goes...
How , this line should be change to the new cs_malloc function u had written:
1.
LLIST *l = cs_malloc(&l, sizeof(LLIST), 0);
pthread_mutex_init(&l->lock, NULL);
return l;
2.
if(!cs_malloc(¶,sizeof(struct read_thread_param), -1)) return FALSE;
para->id=i;
I'm trying to allocate some memory with realloc(). This works so far. But if I want to assign the allocated memory to a pointer in a struct variable, I get a segmentation fault:
// in header
typedef struct {
int a;
char test[20];
} MyContent;
typedef struct {
MyContent* values;
// simmilar to: MyContent values[]
// ... some other stuff
} MyData;
// in source
void myFunction(MyData* dataPtr) {
dataPtr->values = NULL;
MyData* tempPtr = NULL;
for (int i = 1; i < 10; i++) {
tempPtr = (MyContent*) realloc(dataPtr->values, i * sizeof(MyContent));
if (tempPtr == NULL) {
free(dataPtr->values);
break;
}
dataPtr->values = tempPtr; // Here I get the segmentation fault
dataPtr->values[(i-1)].a = 42;
// ...
}
}
I can't figure out what's going wrong here. Any suggestions? Thanks for your help.
Seems like you edited your code. The edited code works just fine.
#include<stdio.h>
#include<malloc.h>
#include<string.h>
// in header
typedef struct {
int a;
char test[20];
} MyContent;
typedef struct {
MyContent* values;
// simmilar to: MyContent values[]
// ... some other stuff
} MyData;
// in source
void myFunction(MyData* dataPtr) {
dataPtr->values = NULL;
MyData* tempPtr;
for (int i = 1; i < 10; i++) {
tempPtr = (MyData*) realloc(dataPtr->values, i * sizeof(MyContent));
if (tempPtr == NULL) {
if(dataPtr->values)
free(dataPtr->values);
printf("realloc() failed\n");
return ;
}
dataPtr->values = (MyContent*)tempPtr; // Here I get the segmentation fault
dataPtr->values[(i-1)].a = 42+i;
strcpy(dataPtr->values[(i-1)].test,"name");
}
}
void PrintData(MyData* dataPtr) {
for (int i = 1; i < 10; i++)
printf("We have %s at %d\n",dataPtr->values[(i-1)].test,dataPtr->values[(i-1)].a);
}
main() {
MyData Sample;
myFunction(&Sample);
PrintData(&Sample);
}
At first glance, I don't see a problem that could cause a crash there - that ones-based addressing is a bit odd, but not incorrect. There could be a problem in the code that you're not showing that results in heap or stack corruption that the realloc call makes worse. Or if you are compiling with optimizations, your debugger might be confused about where the crash is actually occurring. You're also confusing MyData and MyContent, but I'll assume that's just because you made an error while redacting the code.
Note also that if realloc fails, you will crash on the line after the one you indicated, as you'll be writing to a null pointer. You need to abort if tempPtr is NULL, not just free the old pointer. Again, though, this causes a fault on a different line than you indicated.
I'd recommend running your program under valgrind to see where it reports errors - the first such error to occur is likely to be the culprit.
Your condition is wrong for checking the newly allocated memory. It should be:
if (tempPtr == NULL) {
// handle error condition or continue with original 'dataPtr->values'
}
else {
dataPtr->values = tempPtr;
}
Remember that realloc() doesn't necessarily transfer one block to the another block. Sometimes it may allocate the memory in the same pointer region.
I've been trying to build a priority queue in C.
First of all, I do some initialization work such as allocating space.
The following is the Initialize routine and PriorityQueue is a pointer.
void Initialize(int MaxElement, PriorityQueue H)
{
if (MaxElement < MinPQSize)
printf("Priority queue size is too small");
if (!(H = (PriorityQueue)malloc(sizeof(struct HeapStruct))))
printf("Out of space!!!");
if (!(H->Elements = (ElementType *)malloc((MaxElement+1) * sizeof(ElementType))))
printf("Out of space!!!");
H->Capacity = MaxElement;
H->Size = 0;
H->Elements[0] = MinData;
}
Here is how the test code is like
int MaxElement = 15;
PriorityQueue myHeap;
Initialize(MaxElement, myHeap);
But when I try to insert elements into the heap, a segmentation fault pops out.
It can be solved by simply returning the PriorityQueue pointer from Initialize routine.
PriorityQueue Initialize(int MaxElement, PriorityQueue H)
{
...
return H;
}
myHeap = Initialize(MaxElement, myHeap);
So what's happening under the hood?
Is free() invoked when the function returns without a return value?
Thx in advance!
No, even though the H that you're passing in is a pointer, you're trying to change it within the function (with your first malloc). In order to change something, you need to pass a pointer to it. In this case, that means a pointer to a pointer:
void Initialize (int MaxElem, PriorityQueue *H) {
if (MaxElem < MinPQSize)
printf("Priority queue size is too small");
if (!(*H = (PriorityQueue)malloc(sizeof(struct HeapStruct))))
printf("Out of space!!!");
if (!((*H)->Elements = (ElemType *)malloc((MaxElem+1) * sizeof(ElemType))))
printf("Out of space!!!");
(*H)->Capacity = MaxElem;
(*H)->Size = 0;
(*H)->Elements[0] = MinData;
}
Without the extra level on indirection, the H that you change within the function is isolated to the function - it is not reflected back to the caller.
A couple of other points you may want to consider:
You shouldn't cast the return from malloc, it can hide certain errors that you really do want to know about.
If your second malloc fails, you should free the result of the first malloc.
If either of your malloc calls fail, you should return rather than continue, since continuing will cause undefined behaviour if you dereference the null pointer.
You probably don't want to print things from general purpose functions since that's probably an unwanted behaviour. If you must indicate a problem, you're better off passing back an indication to the caller to let them handle it in their own way.
Although to be honest, I actually like the versions that return a value (with no need to pass it in beforehand since you're clearly creating a new thing). Something like this should do:
PriorityQueue Initialize (int MaxElem) {
PriorityQueue H;
if (MaxElem < MinPQSize) {
printf("Priority queue size is too small");
return NULL;
}
if (!(H = malloc(sizeof(*H)))) {
printf("Out of space!!!");
return NULL;
}
if (!(H->Elements = malloc((MaxElem+1) * sizeof(ElementType)))) {
printf("Out of space!!!");
free (H);
return NULL;
}
H->Capacity = MaxElem;
H->Size = 0;
H->Elements[0] = MinData;
return H;
}
PriorityQueue myHeap = Initialize (MaxElement);
You are passing the pointer by value, allow me to illustrate:
char* c = 0;
void set_c(char* ptr)
{
ptr = (char*) malloc(sizeof(char) * 10);
}
// a copy of c is sent in,
set_c(c);
// c doesn't point to the newly allocated data!
To set it correctly, you have to pass your pointer BY pointer, like this:
void set_c_correctly(char** ptr)
{
*ptr = (char*) malloc(sizeof(char) * 10);
}
// a pointer to c is passed in
set_c_correctly(&c);
// now c points to the newly allocated data