My fav Segfault!! why? - c

why this,causes a segfault??
#include<stdio.h>
#include<stdlib.h>
struct node
{
double d;
int *array;
char c;
};
void allocator(struct node *ptr)
{
int *tmp;
tmp = (int*)realloc(ptr, 10);
if(!tmp)
{
ptr->array=tmp;
ptr->array[0] = 23;
}
}
int
main()
{
struct node *ptr = (struct node*)malloc(sizeof(struct node));
ptr->c = 'y';
allocator(ptr);
printf(" %c\n", ptr->c);
printf(" %d\n", ptr->array[0]);
return 0;
}
i got an impression as if the realloc() in the allocator function allocates memory which also maps to the memory allocated by malloc() in the main..
but how does this could happen?? Doesn't the memory manager(i guess the lib(stdlib) here) keeps track of free and allocated spaces in a process??

You're allocating space enough for a struct node then reallocating it to 10 bytes, then accessing the member c which, due to the structure of node, is probably past the 10th byte. This causes a segfault.
Also, if whoever's business it is to decide decides that it needs to move the memory block, realloc returns a pointer to the new location but the pointer back in main still points to the old block which has been reclaimed. This could also cause a segfault.
Also, in this code:
int *tmp;
tmp = (int*)realloc(ptr, 10);
if(!tmp)
{
ptr->array=tmp;
ptr->array[0] = 23;
}
if !tmp, you're accessing a NULL pointer because you're assigning tmp to ptr->array then accessing the 0th element. This could also cause a segfault.
There are many problems in your code. You may need to rewrite much of it.

The problem with this is the attempt to access an unallocated pointer, which happens in main:
printf(" %d\n", ptr->array[0]);
Your allocation function assigns space for ptr, which is a structure, but not for the array within that structure. Possibly this is not what you intended to do (comment your code!).

Related

C11 - Realloc on array of structs fails when doing realloc twice

I'm trying to use malloc and realloc to hold an array of structs. The array should dynamically grow, size should increase by 10 struct elements every time.
Struct:
typedef struct
{
unsigned char foreign_word_[100] = {0};
unsigned char native_word_[100] = {0};
} VocabularyCouple;
In my main, I initialize the array with malloc:
VocabularyCouple* VocStruct = (VocabularyCouple*)malloc(sizeof(*VocStruct) * 10);
Increasing the size of the struct-array seems to work fine in main...
VocabularyCouple* temp = (VocabularyCouple*)realloc(VocStruct, (sizeof(VocabularyCouple) * 20));
if (temp == NULL)
{
printf("ERROR: Out of Memory\n");
return 4;
}
else
{
VocStruct = temp;
free(temp);
temp = NULL;
}
However, if I put the realloc-part into a function like this:
uint8_t resizeVoc(uint32_t new_size, VocabularyCouple **VocStruct)
{
VocabularyCouple *temp = (VocabularyCouple*)realloc(*VocStruct, (sizeof(VocabularyCouple) * new_size));
...
}
I can only call the function once. Every other call will result in this error:
HEAP[VocTest.exe]: Invalid address specified to RtlValidateHeap( 01300000, 01308500 )
Unless I'm missing something, this should be the same problem as c - Realloc an array of Structs, but I just can't get it to work.
Thank you for your help!
VocStruct = temp;
free(temp);
This is wrong, you free all memory as soon as you have allocated it. VocStruct and temp point at the same memory area. Just remove the free().
To clarify, the temp pointer is just there in case realloc fails. Had you written VocStruct = realloc(VocStruct, ... and realloc fails, then you would have overwritten the only pointer to the allocated memory with NULL and created a memory leak. But you only ever have 1 chunk of memory - even though 2 pointers point at it at the same time.

Segment Fualt when I pass a ptr to a function after I malloc a memory, but if I didn't malloc, it was fun?

this is a double circue link. dev_num, blk_num and status are not issued about my question.
typedef struct buf_node {
unsigned dev_num;
unsigned blk_num;
unsigned status:2;
struct buf_node *ptr_prev_free_q;
struct buf_node *ptr_next_free_q;
} stc_buf_header;
this is a buffer node which contented a identity buf_header and a data field
typedef struct {
stc_buf_header *buf_header;
stc_mm *data_area;
} stc_buffer;
this is the double circue link which holds the free buffer node waiting for use(like UNIX)
typedef struct free_lk_node {
stc_buffer *lk_header;
unsigned len;
} stc_free_lk;
AND, now I define a function to init the double circue link
int init(stc_buffer *lk_header, unsigned dev_num, unsigned blk_num){
printf("buf_header\t%p\n", lk_header->buf_header);
printf("lk_header\t%p\n", lk_header);
printf("dev_num\t%d\n", lk_header->buf_header->dev_num);
printf("blk_num\t%d\n", lk_header->buf_header->blk_num);
lk_header->buf_header->dev_num = dev_num;
lk_header->buf_header->blk_num = blk_num;
lk_header->buf_header->status = 0x0;
lk_header->buf_header->ptr_next_free_q = lk_header->buf_header;
lk_header->buf_header->ptr_prev_free_q = lk_header->buf_header;
lk_header->data_area->data = -1; // means that this node is header of the link
}
the printf() statement was used to debug when I got this bug.
OK, now,if I write like this in main()
int main(){
stc_free_lk *link = (stc_free_lk*)malloc(sizeof(stc_free_lk));
init(link->lk_header, (unsigned)0, (unsigned)0);
return 0;
}
when it runs to the point at printf() statement, there will raise a Segment Fualt error
However, if I write like this in main()
int main(){
stc_free_lk link;
init(link.lk_header, (unsigned)0, (unsigned)0);
return 0;
}
EVERYTHING IS OK. WHY??, it makes me confoused...(-o-)#
First of all, use %p for printing addresses, not %d.
And your problem is that malloc just allocates memory, it does not initialize it. And you malloc call only initialized the memory for a struct stc_free_lk object, it does not allocate memory the members that are pointers, you need to allocate memory for them as well.
So lk_header->buf_header is pointing to nowhere, you cannot dereference it, it's undefined behaviour.
What you are seeing is a classic case of undefined behaviour.
Like I said, you have to initialize the member of the struct before you can access them.
You could use calloc instead of malloc because calloc sets the allocated
memory to 0, this helps when initializing pointers in structs.
stc_free_lk *link = calloc(1, sizeof *link);
if(link == NULL)
{
fprintf(stderr, "Not enough memory\n");
return 1;
}
link->header = calloc(1, sizeof *link->header);
if(link->header == NULL)
{
fprintf(stderr, "Not enough memory\n");
free(link);
return 1;
}
init(link->lk_header, (unsigned)0, (unsigned)0);
...
Then in init you should also allocate memory for lk_header->buf_header and
lk_header->data_area and so on.
I suggest that you write a function that allocates all the memory for all the
pointers so that you don't have to allocate memory at different places. That
makes the code hard to follow and hard to find bugs. Also I'd write a destroy
function that frees all allocated memory, again all in one place.

memory free throws segFault

I am implementing symbol table using link list, The code works fine but there is memory leak in code,
I have following structure
struct node
{
char* pcKey;
void* pvValue;
struct node *next;
};
struct _Sym
{
int totalBindings;
struct node *node;
};
add I have sym_new method to allocate memory for sym instance
sym Sym_new (void)
{
_Sym *m_SymTable_t = (_Sym*) malloc (sizeof(_Sym));
if(m_SymTable_t == NULL)
{
return NULL;
}
else
{
m_SymTable_t->totalBindings = 0;
m_SymTable_t->node = NULL;
return m_SymTable_t;
}//endif
}
I am allocating memory for key and value in other function based on the string length.
The free method is
typedef struct _Sym *Sym;
void Sym_free (Sym m_SymTable_t)
{
assert(m_SymTable_t != NULL);
struct node* temp = m_SymTable_t->node;
struct node *currentBinding = NULL;
while(temp != NULL)
{
currentBinding = temp;
temp = temp -> next;
//Removing comment for the below line throws segfault
//free(currentBinding -> pcKey);
//free(currentBinding -> pvValue);
free(currentBinding);
}
free(m_SymTable_t);
}
What is proper way to free the sym completely?
I have uploaded my symTable_Link.cpp file at link
The variables pcKey and pvValue should probably be initialised to null in the Sym_new() function. Otherwise they may contain any old value. This is because malloc doesn't necessarily zero the memory allocated: it just allocates a chunk of memory and the memory could therefore be filled with junk.
So, if for some reason sym_put() is not called for the newly created object these pointers could point to invalid memory and upon your call to free() segfault. If you initialise them to null free() will just ignore them and won't try to free the memory.
A "hacky" DEBUG-only technique you could use to check that the pcKey and pvValue variables are definitely allocated by a sym_put call would be to initialise them in sym_new with a dummy value, for example 0xCDCDCDCD (careful about pointer-widths here... this is why I'm calling this a hacky technique). Then in sym_free check for this magic constant before freeing pcKey and pvValue. If you find it, there's the problem...
Also of interest may be the thread Do I cast the result of malloc?
EDIT:
Looked at the code linked and you appear to be discarding const!
The function id defined as:
int SymTable_put (SymTable_t m_SymTable_t, const char *pcKey, const void *pvValue)
But then does this cast...
temp->pcKey = (char*)pcKey;
temp->pvValue = (char*)pvValue;
This is a bad idea. You're "fooling" the compiler into invalidating your const promise.
THE BUG:
Ok, so you allocate as follows
temp->pcKey = (char*) malloc (sizeof(char) * strlen (pcKey));
But then you overwrite this pointer using
temp->pcKey = (char*)pcKey;
So you a) have a memory leak and b) have just stashed the wrong pointer, which is probs why you get the segfault. You you probably meant to do instead is (strdup is useful here)...
temp->pcKey = strdup(pcKey);
This will allocate new memory for the string in pcKey and COPY the string into the new memory.
I would hazzard a guess you called the function like this...
SymTable_put (xxx, "KEY string", "VALUE string");
Then your code did this
temp->pcKey = (char*)malloc (sizeof(char) * strlen (pcKey));
...
temp->pcKey = (char*)pcKey;
So now temp->pcKey points to "KEY string" itself and not a copy of it. So when you try to free the string constant, your program complains. What you want to do is copy the string from pcKey into temp->pcKey instead of overwriting the pointer.
EDIT:
As per comments the mallocs need space + 1 to include the null terminator. Also sizeof(char) is always 1, so is redundant. Try strdup instread.

Seg Fault when copying a pointer

How come the following code result in seg fault? Basically after I copy the head pointer to temp, the head pointer gone.
typedef struct address * paddress; // defines struct pointer
void addAddressToList(paddress head, int addr[])
{
if (head == NULL) {
//head->addrArray = addr; // if list is initially empty
} else {
paddress temp;
temp = head;
while (temp->right != NULL) {
temp = temp->right; // go to end of the list
}
paddress newAddress = (paddress)malloc(sizeof(paddress*));
newAddress->intAddr = addr;
newAddress->right = NULL;
newAddress->left = temp; // connect the new address
temp->right = newAddress;
}
}
main() {
paddress addressListHead;
addressListHead = (paddress)malloc(sizeof(paddress*));
int intAddr1[] = {1,2,3,4,5,6,7};
char hexAddr1[] = "123456";
int intAddr2[] = {16,14,13,12,11};
char hexAddr2[] = "fedcb";
addressListHead->intAddr = intAddr1;
addressListHead->hexAddr = hexAddr1;
addAddressToList(addressListHead, intAddr2);
}
paddress addressListHead;
addressListHead = (paddress)malloc(sizeof(paddress*));
It seems to get rid of the compilation error, you have type casted what malloc is returning to paddress. addressListHead is a pointer, which means it can hold the address of an object but not the address of a pointer. The malloc here statement doesn't create an object. You need to change this -
addressListHead = (paddress)malloc(sizeof(paddress*));
to
addressListHead = (paddress)malloc(sizeof(struct address));
in main and addAddressToList functions.
Segmentation fault :
else {
paddress temp;
temp = head;
while (temp->right != NULL) {
temp = temp->right; // go to end of the list
}
I understand paddress::right is a pointer with the fact you are comparing it to NULL. But what is temp::right is initialized to. It is pointing to some garbage address and so you cannot ask for it to compare with NULL. Make it point to a valid memory location.
There is more than one problem in your code.
Firstly, the usual advice: stop using sizeof with type names (as much as possible). Use sizeof with expressions, not types. Type names belong in declarations and nowhere else.
Your problem with memory allocation could have been prevented if you used this malloc idiom
T *p = malloc(n * sizeof *p);
i.e. sizeof should be applied to *p, where p is the pointer to the array you are allocating and n is the total number of elements in that array. That way you never have to guess what type name you should specify under sizeof (an that way your code becomes type-independent).
In your case you are allocating just one object, so the code should look as
paddress newAddress = malloc(sizeof *newAddress);
(And don't cast the result of malloc - there's absolutely no point in doing that).
Secondly, when you the head element of the list, you need to initialize all the fields. Yet you never initialize right (or left) in the head element. Hence the crash even when the correct amount of memory is allocated.
In main(), you want
addressListHead = (paddress)malloc(sizeof(address));
That makes sure you get enough bytes to hold an address.
First error:
addressListHead = (paddress)malloc(sizeof(paddress*));
paddress* means a pointer to paddress which itself is a pointer to struct address. Hence paddress* is a pointer to a pointer to struct address. You would want to do:
addressListHead = (paddress)malloc(sizeof(struct address));
Also, I see that you made a similar mistake yesterday. Why do I get a seg fault? I want to put a char array pointer inside a struct
It's important to understand the concept of pointers properly. I would definitely recommend you to go through some tutorials on pointers. If you need help with that, let me know.

initializing a data structure in C to manage a pool of memory

i am writing a simple function for a library, that will take in as a parameter the size of memory to be managed by my other functions.
i have a data structure that holds the information of this large memory pool initialized by the user.
typedef struct memBlock{
struct memBlock* next;
unsigned int size; // Size of this block
unsigned int is_used; // bool 0 = not used 1 = used
} memBlock;
I also have this function that i am trying to figure out how to initialize this data structure as well as allocate enough space to be managed initially?
int initialize_memory(unsigned long size){
memBlock *ptr; // the beginning of our whole memory to be handled
ptr = malloc(size); // this is the ptr to the original memory first allocated.
ptr->next = NULL;
ptr->size = NULL;
ptr->is_used = 0;
has_initialized = 1; // the memory has been initialized
}
please help
Change ptr->size = NULL; to ptr->size = size;. You also need to return ptr, or store it somewhere. Your function returns int, but you don't return anything. has_initialized seems unnecessary -- you know you've initialized because your memory pool (the ptr value you will return) isn't NULL. If you need more help than that, you're going to have to explain more.
Addendum: You need to decide whether memBlock.size is the size of the allocated space or the size of the memory block represented by the memBlock ... if the latter, then you need to account for the space occupied by the memblock itself by subtracting that off the amount of space you allocated: ptr->size = size - sizeof(struct memBlock); You also need a way to address your memory pool ... since that immediately follows the memBlock, its address is (ptr + 1) or &ptr[1] (if you don't understand that, look up "pointer arithmetic in C").
P.S. You wrote in a comment "Essentially i also have another function that will act like 'malloc' to reserve a number of bytes but will first check this data structure to see if any memory is available from my pool"
Why do you want to do that? malloc already manages memory far better than your function will, considering the skill level and time invested, and there's no point in layering another memory allocator on top of it. Unless this is a school project to write a memory allocator, in which case you should say that up front.
typedef struct memBlock {
unsigned int size;
unsigned int initialized;
void* block;
} memBlock;
memBlock* new_memBlock(unsigned int size)
{
memBlock* memblock;
memblock = malloc(sizeof(memBlock));
if (memblock)
{
memblock->size = size;
memblock->block = malloc(size);
if (memblock->block)
memblock->initialized = 1;
}
return memblock;
}
void free_memBlock(memBlock** memblock)
{
if (*memblock)
{
free(*memblock->block)
*memblock->block = 0;
}
free(*memblock);
*memblock = 0;
}
void main()
{
memBlock* memblock = new_memBlock(1024);
if (memblock && memblock->initialized)
printf("Initialized\n");
else
printf("Not initialized\n");
free_memBlock(&memblock);
}

Resources