Invalid write of size 8 after a malloc - c

I am currently working on a project for my school and I am having issues with my code. The purpose of the programm is to implement a plugin manager that search in a directory all "*_plugin.so" file and add a plugin descriptor into a simple linked list.
The C code :
//struct of a single node
typedef
struct _chainon_ {
plugin_descriptor * desc;
struct _chainon_ * next;
} Chainon;
// manager that contains sentry node & number of plugins contained by the list
struct plugin_manager_t {
int nbElts;
Chainon * sentinel;
};
typedef
struct {
const char * m_name; // nom du filtre
const char * m_description; // description de l'effet du filtre
filter_function m_filtre; // fonction de réalisation du filtre
} plugin_descriptor;
Now the register_plugin function, it is called while the programm find a new plugin in the directory, it calls an init_ function that call register_plugin :
void
init_(plugin_manager * pm)
{
register_plugin(pm,
"null_filter",
"Exemple de filtre inutile",
null_filter);
}
and then it is supposed to add the new plug to the list :
void
register_plugin(plugin_manager * pm,
const char filter_name[],
const char filter_description[],
filter_function the_filter)
{
Chainon * n = (Chainon *)malloc(sizeof(Chainon)); //new node that i want to add to the linked list
n->desc = NULL;
n->next = NULL;
n->desc->m_name = filter_name;
n->desc->m_description = filter_description;
n->desc->m_filtre = the_filter;
Chainon * current = pm->sentinel;
for(int i=0;i<pm->nbElts;i++){
current=current->next;
i++;
}
current->next = n;
}
And that is what I am getting with valgrind while I execute this programm :
> ==7022== Invalid write of size 8
> ==7022== at 0x4015A7: register_plugin (pluginmanager.cc:165)
> ==7022== by 0x66E1BDC: init_ (null_filter_plugin.cc:23)
> ==7022== by 0x401483: discover_plugins (pluginmanager.cc:113)
> ==7022== by 0x401187: main (main.cc:17)
> ==7022== Address 0x0 is not stack'd, malloc'd or (recently) free'd
> ==7022==
> ==7022==
> ==7022== Process terminating with default action of signal 11 (SIGSEGV)
> ==7022== Access not within mapped region at address 0x0
> ==7022== at 0x4015A7: register_plugin (pluginmanager.cc:165)
> ==7022== by 0x66E1BDC: init_ (null_filter_plugin.cc:23)
> ==7022== by 0x401483: discover_plugins (pluginmanager.cc:113)
> ==7022== by 0x401187: main (main.cc:17)
> ==7022== If you believe this happened as a result of a stack
> ==7022== overflow in your program's main thread (unlikely but
> ==7022== possible), you can try to increase the size of the
> ==7022== main thread stack using the --main-stacksize= flag.
> ==7022== The main thread stack size used in this run was 8388608.
I am novice at C programming
But I do not understand why I could not initialize "n->desc->name" since I allocated the memory with malloc and then initialized everything to NULL ?
Any help would be appreciate !
Thank you

Your code has several problems, some of them are minor problems and others are causing the posted valgrind output,
Is not really a problem, it's just that you don't need to cast the return value of malloc()
Chainon *n = malloc(sizeof(Chainon));
is ok, no need for the cast.
You need to check that malloc() succeeded, not just assume that it did, under normal situations it will not fail, but in case of failure your program does not handle that, and in case it has some sensitive data that needs to be stored in the hard drive or any other situation where a clean exit is needed, you will cause a lot of problems to the program users, so you should ensure that your program exits cleanly, hence checking the return value of malloc() is a very good thing to do, just check against NULL right after every call to malloc() and handle that according to the situation where the failure occurs.
You don't allocate space for your struct members, every pointer must point to valid memory before dereferencing it, so you must ensure that it does point to valid memory, uninitialized pointers can't be checked so in cases where you are going to initialize the pointer after a possible check, initialize it to NULL.
You do that in one case, but then you dereference the NULL pointer, which is undefined behavior.
Using all the recommendations above, your function has to be re-written like this*
void
register_plugin(plugin_manager * pm,
const char *const filter_name,
const char *const filter_description,
filter_function the_filter)
{
Chainon *chainon;
plugin_descriptor *descriptor;
Chainon *current
int i;
if (pm == NULL)
return;
chainon = malloc(sizeof(*chainon));
if (chainon == NULL)
return;
chainon->next = NULL;
descriptor = malloc(sizeof(*descriptor));
if (descriptor == NULL)
{
free(chainon);
return;
}
chainon->desc = descriptor;
descriptor->m_name = filter_name;
descriptor->m_description = filter_description;
descripotor->m_filtre = the_filter;
current = pm->sentinel;
if (current == NULL)
return;
for(i = 0 ; ((i < pm->nbElts) && (current->next != NULL)) ; ++i)
current = current->next;
current->next = chainon;
}
*Some of the things I changed are not really necessary. I just think it's better that way.

Related

Access violation of dynamic array for hashmap

I am having an issue with the table of a little hashmap I am trying to implement.
map.h
typedef struct Map Map;
Map *map_create();
int map_set(Map *map, char *key, void *val);
map.c
const int MAP_INITIAL_SIZE = 100;
typedef struct MapPair MapPair;
struct MapPair
{
char *key;
void *val;
};
struct Map
{
MapPair **table;
int count;
int limit;
};
Map *map_create(void)
{
Map *map = (Map*)malloc(sizeof(Map));
if (!map) return NULL;
map->table = (MapPair**)malloc(MAP_INITIAL_SIZE * sizeof(MapPair));
if (!map->table)
{
free(map);
return NULL;
}
map->count = 0;
map->limit = MAP_INITIAL_SIZE;
return map;
}
void add(MapPair **context, int start, MapPair *pair, int limit)
{
int i = start;
while (context[i] != NULL && strcmp(context[i]->key, pair->key) != 0) // crashing here
{
i++;
if (i == limit) i = 0;
}
context[i] = pair;
}
int map_set(Map *map, char *key, void *val)
{
if (map->count >= map->limit / 2)
{
if (!expand(map)) return 0;
}
MapPair *pair = (MapPair*)malloc(sizeof(MapPair));
if (!pair) return 0;
pair->key = key;
pair->val = val;
add(map->table, hash(key, map->limit), pair, map->limit);
++map->count;
return 1;
}
I was originally developing in pelles c but moved to vs2013 for the debugger when I was experiencing problems. Then in vs2013 the program would crash at the add function but not in pelles c. I am assuming it has something to do with my dynamic array that I plan to be able to expand later.
Can anybody tell me why the program seems to crash when I try to access an index of the dynamic array?
In add function you are checking the table, until you reach the NULL pointer:
while (context[i] != N ...
But when you allocate this table you never set any of those pointers to NULL:
map->table = (MapPair**)malloc(MAP_INITIAL_SIZE * sizeof(MapPair));
You should set them to NULL:
for( size_t i = 0 ; i < MAP_INITIAL_SIZE ; i++ )
map->table[i] = NULL ;
Otherwise you will go out of bounds of that array.
I didn't know Visual could compile pure C projects ! Anyway, your crash is caused by a magic string : http://en.wikipedia.org/wiki/Magic_number_(programming)
* 0xABABABAB : Used by Microsoft's HeapAlloc() to mark "no man's land" guard bytes after allocated heap memory
* 0xABADCAFE : A startup to this value to initialize all free memory to catch errant pointers
* 0xBAADF00D : Used by Microsoft's LocalAlloc(LMEM_FIXED) to mark uninitialised allocated heap memory
* 0xBADCAB1E : Error Code returned to the Microsoft eVC debugger when connection is severed to the debugger
* 0xBEEFCACE : Used by Microsoft .NET as a magic number in resource files
* 0xCCCCCCCC : Used by Microsoft's C++ debugging runtime library to mark uninitialised stack memory
* 0xCDCDCDCD : Used by Microsoft's C++ debugging runtime library to mark uninitialised heap memory
* 0xDEADDEAD : A Microsoft Windows STOP Error code used when the user manually initiates the crash.
* 0xFDFDFDFD : Used by Microsoft's C++ debugging heap to mark "no man's land" guard bytes before and after allocated heap memory
* 0xFEEEFEEE : Used by Microsoft's HeapFree() to mark freed heap memory
(SO source : In Visual Studio C++, what are the memory allocation representations?)
Unlike GCC (or pelles I imagine), Visual Studio set uninitialized heap array pointers as 0xCDCDCDCD, not NULL. So your check of context[i] != NULL returns true even though context is not initialized.
... And that's why explicit is always better than implicit.

Personal malloc function that uses a data structure to handle memory

I have this function that will take in a number of bytes to allocate and send back only if it is available and the size of the requested number of bytes fit into my small managed memory.
My question:
The appropriate data structure is not being allocated for and I'm afraid I will not get back correct addresses. Does anyone know how I can test this function using it as a library in another program?
THE DATA STRUCTURE
typedef struct memBlock{
struct memBlock* next;
unsigned long size; // Size of this block
unsigned int is_used; // bool 0 = not used 1 = used
} memBlock;
THE MALLOC FUNCTION:
char *mm_alloc(unsigned long no_of_chars){
if (!has_initialized) {
printf("No Memory has been intialized, PLEASE INITIALIZE THE MEMORY BEFORE calling This function\n");
exit(1);
}
void *cur_location; // this is where we are currentl in our memory pool
memBlock *current_loc_mb; // the current mem block location
char *mem_location; // mem location we will return to the user
/* We are going to have to include the size of our data struct when we are searching for open memory*/
no_of_chars = no_of_chars + sizeof(struct memBlock);
mem_location = 0; // set to 0 until a proper size has been found
cur_location = managed_memory_start; // start at the beginning of our allocated memory
// go until there is no more memory left, allocate until we get to the end of our managed memory
while (managed_memory_start != NULL) {
/*cur_location and cur_loc_mcb are at the same address initially,
but we use the current location as a pointer to move around our managed memory*/
cur_loc_mcb = (memBlock *)cur_location;
// if our current location is not used
if (!cur_loc_mcb->is_used) {
if (cur_loc_mcb->size >= no_of_chars) {
// we have found a size big enough or equal to what the user asks for
cur_loc_mcb->is_used = 1;
mem_location = cur_location;
break;
}
}
// at this point we dont have a size big enough, move to the next one
cur_location = cur_location + cur_loc_mcb->size;
}
/*Move the memory past or MCB and return*/
mem_location = mem_location + sizeof(struct memBlock);
return mem_location;
}
Somewhere in your code you set mem_location
mem_location = cur_location;
and later, just before returning its value, you change it
mem_location = mem_location + sizeof(struct memBlock);
it doesn't seem right ...

How to use free on a handle inside a list?-> C -> windows API

I have a list in C that is something like this:
typedef struct _node
{
int number;
DWORD threadID;
HANDLE threadH;
struct *_node next;
} *node;
And you have somthing like this:
node new_node = malloc(sizeof(node));
As you may have guessed out, this list will store information for threads, including their handlers and Id's. Still I am having trouble when I try to do this:
free(new_node);
Everytime I try to do this I encounter an unexpected error, VS saying that there was a data corruption. I've pinned down as much as possible and I found that the problem resides when I try to use free the handle.
I've searched on MSDN how to do this but the only thing I can find is the function that closes the thread (which is not intended here, since I want the thread to run, just deleting it's record from the list).
The question is: how I am supposed to free an handle from the memory? (Considering that this is only a copy of the value of the handle, the active handle is not being deleted).
EDIT: This is the function to insert nodes from the list:
int insereVisitanteLista(node* lista, DWORD threadID, HANDLE threadH, int num_visitante)
{
node visitanteAnterior;
node novoVisitante = (node)malloc(sizeof(node));
if(novoVisitante == NULL)
return 0;
novoVisitante->threadID = threadID;
novoVisitante->threadH = threadH;
novoVisitante->number = num_visitante;
novoVisitante->next = NULL;
if(*lista == NULL)
{
*lista = novoVisitante;
return 1;
}
visitanteAnterior = *lista;
while(visitanteAnterior->next != NULL)
visitanteAnterior = visitanteAnterior->next;
visitanteAnterior->next =novoVisitante;
return 1;
}
And this is the function to delete nodes:
int removeVisitanteLista(node * lista, DWORD threadID)
{
node visitanteAnterior = NULL, visitanteActual;
if(*lista == NULL)
return 0;
visitanteActual = *lista;
if((*lista)->threadID == threadID)
{
*lista = visitanteActual->next;
visitanteActual->next = NULL;
free(visitanteActual);
return 1;
}
while(visitanteActual != NULL && visitanteActual->threadID != threadID)
{
visitanteAnterior = visitanteActual;
visitanteActual = visitanteActual->next;
}
if (visitanteActual == NULL)
return 0;
visitanteAnterior->next = visitanteActual->next;
free(visitanteActual);
return 1;
}
What exactly is a node that you are trying to free? Is this a pointer to a struct _node? If yes, have you allocated it previously? If no, free is not needed, otherwise you have to check if node is not NULL and make sure you do not free it multiple times. It is hard to guess what you are doing and where is an error without a minimal working example reproducing the problem. The only thing I can suggest is to read about memory management in C. This resource might help.
UPDATE:
node in your code is a pointer to _node. So sizeof (node) is a size of a pointer, which is either 4 or 8 bytes (depending on architecture). So you allocate 8 bytes, for example, but assume you have a pointer to the structure which is much larger. As a result, you corrupt memory, and behavior of the program becomes undefined. So changing node novoVisitante = (node)malloc(sizeof(node)) to node novoVisitante = (node)malloc(sizeof(_node)) should fix the problem.
You haven't shown us the context of your call to free() so I need to speculate a little but my first concern is that you didn't mention removing the node from the list before deleting it.
Start by unlinking the node by modifying the next field of the previous (or head) node. If you still get the error, then you have corrupted memory somehow by writing past the end of one of your allocated memory structures or something similar.
Also, I assume node is a pointer. You really haven't provided much information about what you're doing.

*glibc detected double free or corruption() * message!

The following deleteNode function when I run the program gets these:
* glibc detected free(): invalid next size (normal): 0x000000000103dd90 **
Even i make the ' free(here); ' a comment,i get the above message.
I dont think that the other 'free' calls provokes a problem like that. But I cant see why this would be wrong. :/
struct List *deleteNode(int Code,int i,char* Number)
{
struct List *here;
here=Head;
for (here; here!=Tail; here=here->next)
{
if ( (here->number==Number) && (here->code==Code) )//found node on the List
{
if (here->previous==Head) //delete from beginning
{
Head=here->next;
here->next->previous=Head;
}
else if (here->next==Tail) //delete from the end
{
here->previous->next=Tail;
Tail=here->previous;
}
else //delete from the middle of the list
{
here->previous->next=here->next;
here->next->previous=here->previous;
}
break;
}
}
free (here);
}
EDIT:
if i used and understand valgring well then the problem is on my main function.
i have also there some 'free' but i changed deleteNode before this message so i thought that the problem was on the deleteNode function.
Now,there is no free() invalid next size.... but unfortunately this:
glibc detected * : double free or corruption (out): 0x00007fff1aae9ae0 *
:(
A part of the main:
FILE *File;
if ( ( File=fopen("File.txt","r")) !=NULL )
{
int li = 0;
char *lin = (char *) malloc(MAX_LINE * sizeof(char));
while(fgets(lin, MAX_LINE, eventFile) != NULL)
{
token = linetok(lin, " ");
if(token != NULL)
{
int i,code,nodeID;
char *number;
char *event;
for(i = 0; token[i] != NULL; i += 1)
{
code=atoi(token[0]);
strcpy(event,token[1]);
nodeID=atoi(token[2]);
strcpy(number,token[3]) ;
int i;
if (!strcmp(event,"add"))
{
add_to_List(code,i,number);
}
else if(!strcmp(event,"delete"))
{
deleteNode(eventNo,i,number);
}
free(event);
free(phoneNumber);
}
free(token);
}
else
{
printf("Error reading line %s\n", lin);
exit(1);
}
}
}
else
{
printf("Error opening file with the events.\nEXIT!");
exit(0);
}
debugging it...
multiple definition of main'
pro:(.text+0xce0): first defined here
/usr/lib/gcc/x86_64-linux-gnu/4.4.1/crtend.o:(.dtors+0x0): multiple definition ofDTOR_END'
pro:(.dtors+0x8): first defined here
/usr/bin/ld: warning: Cannot create .eh_frame_hdr section, --eh-frame-hdr ignored.
/usr/bin/ld: error in pro1(.eh_frame); no .eh_frame_hdr table will be created.
collect2: ld returned 1 exit status
"Invalid next size" means that glibc has detected corruption in your memory arena.
You have overwritten valuable accounting information that's stored in between your allocated blocks.
With each block that malloc gives you, there is some accounting information stored close by. When you overwrite this information by, for example, writing 128 characters to a 20-character buffer, glibc may detect this the next time you try to free (or possibly allocate) some memory.
You need to find the root cause of this problem - it's not the free itself, that's just where the problem is being detected. Somewhere, some of your code is trashing memory and a memory analysis tool like valgrind will be invaluable here.
If the node is not found in the list, you will free the Tail node at the end of the function, without updating Tail to point to anything valid again.
Further using the list and the now deallocated Tail can easily result in memory corruption that might later be detected by glibc with a message like the one you got.
Also note that in (here->number==Number) you are comparing two pointers, not the values those pointers point to. I'm not sure if that's what you want.

Running out of memory.. How?

I'm attempting to write a solver for a particular puzzle. It tries to find a solution by trying every possible move one at a time until it finds a solution. The first version tried to solve it depth-first by continually trying moves until it failed, then backtracking, but this turned out to be too slow. I have rewritten it to be breadth-first using a queue structure, but I'm having problems with memory management.
Here are the relevant parts:
int main(int argc, char *argv[])
{
...
int solved = 0;
do {
solved = solver(queue);
} while (!solved && !pblListIsEmpty(queue));
...
}
int solver(PblList *queue) {
state_t *state = (state_t *) pblListPoll(queue);
if (is_solution(state->pucks)) {
print_solution(state);
return 1;
}
state_t *state_cp;
puck new_location;
for (int p = 0; p < puck_count; p++) {
for (dir i = NORTH; i <= WEST; i++) {
if (!rules(state->pucks, p, i)) continue;
new_location = in_dir(state->pucks, p, i);
if (new_location.x != -1) {
state_cp = (state_t *) malloc(sizeof(state_t));
state_cp->move.from = state->pucks[p];
state_cp->move.direction = i;
state_cp->prev = state;
state_cp->pucks = (puck *) malloc (puck_count * sizeof(puck));
memcpy(state_cp->pucks, state->pucks, puck_count * sizeof(puck)); /*CRASH*/
state_cp->pucks[p] = new_location;
pblListPush(queue, state_cp);
}
}
}
free(state->pucks);
return 0;
}
When I run it I get the error:
ice(90175) malloc: *** mmap(size=2097152) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
Bus error
The error happens around iteration 93,000.
From what I can tell, the error message is from malloc failing, and the bus error is from the memcpy after it.
I have a hard time believing that I'm running out of memory, since each game state is only ~400 bytes. Yet that does seem to be what's happening, seeing as the activity monitor reports that it is using 3.99GB before it crashes. I'm using http://www.mission-base.com/peter/source/ for the queue structure (it's a linked list).
Clearly I'm doing something dumb. Any suggestions?
Check the result of malloc. If it's NULL, you might want to print out the length of that queue.
Also, the code snippet you posted didn't include any frees...
You need to free() the memory you've allocated manually after you're done with it; dynamic memory doesn't just "free itself"

Resources