Why does the second malloc fail in this scenario? - c

I am currently working on a piece of code where we are parsing a file and working with different functions. Through debugging with printf calls, I have found that I am getting a memory error on the second malloc call. What could cause the second malloc to fail in this rough skeleton?
struct example {
char *myChar;
int myInt;
};
struct example *doThing(FILE *file) {
struct example *myToken = (struct example *)malloc(sizeof(struct example));
char buffer[32] = "";
// other stuff
if (strncmp(buffer, "random", 6) == 0) {
strncpy(myToken->myChar, buffer, 6);
myToken->tokenid = 1;
return myToken;
}
return NULL;
}
struct example *doThing2(FILE *file) {
struct example *myOtherToken = (struct example *)malloc(sizeof(struct example));
// other stuff
return myOtherToken;
}
int main() {
FILE *ofp = fopen("thefile.txt", "r");
struct example *token1, *token2;
token1 = doThing(ofp);
token2 = doThing2(ofp);
// other stuff
free(token1);
free(token2);
return 0;
}

You are facing memory leak.
correct your code folowing one of the two samples bellow
and yes, as #Eugene_Sh mentioned, you should allocate memory for myToken->myChar and do not forget to free it before freeing myToken
SAMPLE 1
struct example* doThing(FILE *file) {
char buffer[32] = "";
// other stuff
if (strncmp(buffer, "random", 6) == 0) {
struct example *myToken = (struct example *) malloc(sizeof(struct example));
myToken ->myChar= malloc(7);
strncpy(myToken ->myChar, buffer, 6);
myToken ->myChar[6]=0;
myToken->tokenid = 1;
return myToken;
}
return NULL;
}
SAMPLE 2
struct example* doThing(FILE *file) {
struct example *myToken = (struct example *) malloc(sizeof(struct example));
char buffer[32] = "";
// other stuff
if (strncmp(buffer, "random", 6) == 0) {
myToken ->myChar= malloc(7);
strncpy(myToken ->myChar, buffer, 6);
myToken ->myChar[6]=0;
myToken->tokenid = 1;
return myToken;
}
free(myToken );
return NULL;
}

Related

Dynamic reallocation an array of structures with malloc and realloc

I am really having a difficult time trying to create an array of structures using malloc and realloc. I have posted mostly the entire code base, or at least the relevant information pertaining to the question below.
struct _section {
char *sectName;
int start_addr;
int end_addr;
char *bytes;
};
struct _section *get_exe_sections(struct _section *exe_sect, Elf *elf, GElf_Ehdr *ehdr, GElf_Shdr *shdr, Elf_Data *data) {
exe_sect->sectName = elf_strptr(elf, ehdr->e_shstrndx, shdr->sh_name);
exe_sect->start_addr = shdr->sh_addr;
exe_sect->end_addr = shdr->sh_addr + shdr->sh_size;
exe_sect->bytes = (unsigned char *)data->d_buf;
return exe_sect;
}
int main(int argc, char *argv[]) {
Elf *elf;
int fd;
//process input file
int sections_count = count_sections(elf);
GElf_Ehdr ehdr_mem;
GElf_Ehdr *ehdr = gelf_getehdr(elf, &ehdr_mem);
struct _section *exe_sect = (struct _section *)malloc(sizeof(struct _section));
for(int cnt = 0; cnt < sections_count; cnt++) {
Elf_Scn *scn = elf_getscn(elf, (size_t)cnt);
GElf_Shdr shdr_mem;
GElf_Shdr *shdr = gelf_getshdr(scn, &shdr_mem);
Elf_Data *data = elf_getdata(scn, NULL);
if(ehdr == NULL || shdr == NULL)
exit(1);
if(strcmp(header_name(SECT_TYPE, GELF_ST_TYPE(shdr->sh_type)), "PROGBITS") == 0) {
if(strcmp(flag_name(SECT_FLAGS, shdr->sh_flags), "ALLOC & EXECUTE") == 0 || \
strcmp(flag_name(SECT_FLAGS, shdr->sh_flags), "EXECUTE") == 0) {
exe_sect = get_exe_sections(exe_sect, elf, ehdr, shdr, data);
struct _section *nxt_sect = (struct _section *)realloc(exe_sect, 2*sizeof(*exe_sect));
if(nxt_sect != NULL)
exe_sect = nxt_sect;
}
}
}
return 0;
}
What I am having trouble with is creating an array of structures dynamically and using malloc and realloc to resize the structure to fit more data into it. If I were to place a handful of print statements are the bottom of main the output will give me the last data that was input to the structure. How would I go about accessing individual entries that were made during each call to get_exe_section? From prior posts and other resources I thought this would work, but I cannot create an array in this manner. Any form of help would be great. Thanks.
You could add another element in your struct that points to the next section. This way you could create a linked list
struct _section {
char *sectName;
int start_addr;
int end_addr;
char *bytes;
struct _section *next; // pointer to next section
};
You could use another Struct to point to the head of your list.
and then instead of using realloc. you could just do
exe_sect->next = (struct _section *)malloc(sizeof(struct _section));
Here is how I would change the main function :
int main(int argc, char *argv[]) {
Elf *elf;
int fd;
//process input file
int sections_count = count_sections(elf);
GElf_Ehdr ehdr_mem;
GElf_Ehdr *ehdr = gelf_getehdr(elf, &ehdr_mem);
struct _section *exe_sect = (struct _section *)malloc(sizeof(struct _section));
for(int cnt = 0; cnt < sections_count; cnt++) {
Elf_Scn *scn = elf_getscn(elf, (size_t)cnt);
GElf_Shdr shdr_mem;
GElf_Shdr *shdr = gelf_getshdr(scn, &shdr_mem);
Elf_Data *data = elf_getdata(scn, NULL);
if(ehdr == NULL || shdr == NULL)
exit(1);
if(strcmp(header_name(SECT_TYPE, GELF_ST_TYPE(shdr->sh_type)), "PROGBITS") == 0) {
if(strcmp(flag_name(SECT_FLAGS, shdr->sh_flags), "ALLOC & EXECUTE") == 0 || \
strcmp(flag_name(SECT_FLAGS, shdr->sh_flags), "EXECUTE") == 0) {
exe_sect = get_exe_sections(exe_sect, elf, ehdr, shdr, data);
exe_sect->next = (struct _section *)malloc(sizeof(struct _section));
if(exe_sect->next != NULL)
exe_sect = exe_sect->next;
}
}
}
return 0;
PS : To access all the individual entries, add another struct that consists of a pointer to the head of the list, and a variable that keeps count.

Linked list add function results in a segmentation fault

Calling this value works for the first 2 calls and then causes a segmentation fault.
void insert_message(char *id, char *message) {
if (first_message == NULL) {
first_message = malloc( sizeof(struct server_message) );
strcpy(first_message->id, id);
strcpy(first_message->message, message);
first_message->next_msg = NULL;
} else {
struct server_message *curr_msg = first_message;
while (curr_msg != NULL) {
curr_msg = curr_msg->next_msg;
}
curr_msg->next_msg = malloc( sizeof(struct server_message) );
strcpy (curr_msg->next_msg->id, id);
strcpy (curr_msg->next_msg->message, message);
curr_msg->next_msg->next_msg = NULL;
}
}
First Message and Server Message struct:
// used to store messages.
struct server_message {
char message[80];
char id[80];
struct server_message *next_msg;
};
//head of the list
static struct server_message *first_message = NULL;
Your loop finishes when curr_msg == NULL holds. Calling curr_msg->next_msg = malloc( sizeof(struct server_message) ); will fail since you cannot dereference NULL. Hence do the following:
while (curr_msg->next_msg != NULL) {
curr_msg = curr_msg->next_msg;
}
// curr_msg is now the last node in your list
As per your loop , after came out of loop , you have to allocate memory for curr_msg & you have to fill the necessary info in that curr_msg structure. Because in your curr_msg structure ,already you stored the link to next_msg
so you have to modify your code like below
while (curr_msg != NULL)
{
curr_msg = curr_msg->next_msg;
}
curr_msg = malloc( sizeof(struct server_message) );
strcpy (curr_msg->id, id);
strcpy (curr_msg->message, message);
curr_msg->next_msg = NULL;

Hashtable Add - C

Getting some segfault on the following algorithm to add an element to the correct bucket in a hashtable.
My structures are basic:
struct kv {
char* key;
unsigned val;
struct kv* next;
};
struct hashtable {
struct kv** table;
unsigned size;
};
And my buggy function:
struct kv* ht_find_or_put(char* word, unsigned value,
struct hashtablet* hashtable,
unsigned (*hash)(char*))
{
unsigned index = hash(word) % hashtable->size;
struct kv* ke = malloc(sizeof (struct kv));
for (ke = hashtable->table[index]; ke != NULL; ke = ke->next)
{
if (strcmp(ke->key, word) == 0)
return ke;
}
if (ke == NULL)
{
ke->key = word;
ke->val = value;
ke->next = hashtable->table[index];
hashtable->table[index] = ke;
}
return ke;
}
I know I haven't added yet all the tests (if malloc failed and such) just trying to debug this particular problem...
I'm allocating my table as such:
struct hashtable* hashtable_malloc(unsigned size)
{
struct hashtable *new_ht = malloc(sizeof(struct hashtable));
new_ht->size = size;
new_ht->table = malloc(sizeof(struct kv) * size);
for(unsigned i = 0; i < size; i++)
new_ht->table[i] = NULL;
return new_ht;
}
Any sort of help will greatly be appreciated. I'm only starting to learn.
The first issue is a memory leak, e.g. - you allocate memory using malloc, but than loses the reference to it, as you override the pointer:
// allocate memory
struct kv* ke = malloc(sizeof (struct kv));
// lose the reference
// VVVVVVVVVVV
for (ke = hashtable->table[index]; ke != NULL; ke = ke->next)
The second issue, which probably causes the segfault, is that you try to de-reference a null pointer:
if (ke == NULL)
{
// ke is NULL, you can't de-reference it
ke->key = word;
ke->val = value;
ke->next = hashtable->table[index];
hashtable->table[index] = ke;
}
The solution will be, IMHO, to allocate and put the new element, only upon failure to find it:
struct kv* ht_find_or_put(char* word, unsigned value, struct hashtablet* hashtable, unsigned (*hash)(char*))
{
unsigned index = hash(word) % hashtable->size;
struct kv* ke;
// first we try to find the node
for (ke = hashtable->table[index]; ke != NULL; ke = ke->next)
{
if (strcmp(ke->key, word) == 0)
return ke;
}
// didn't find it - lets create and put a new one.
if (ke == NULL)
{
ke = malloc(sizeof (struct kv));
// later add a check if the allocation succeded...
ke->key = word;
ke->val = value;
ke->next = hashtable->table[index];
hashtable->table[index] = ke;
}
return ke;
}
Since I didn't want to introduce entirely new code, that would just confuse you, I made the minimal changes to the original code.

C - pointer to array of pointers

i have to store the pointers of a data structure.
So, i need an array of pointer.
I created a simple example, but i receive a segmentation fault.
Why i cannot do
buf->data[i] = pkt ??
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define MAX_SIZE 500000
#define MAX_CHAR 1024
char *string = "HelloHelloHello";
struct pkt {
char *buf;
int seq;
};
struct buffer {
int a;
int b;
struct pkt **data;
};
struct buffer *new_buffer() {
struct buffer *new;
new = malloc(sizeof(struct buffer) * MAX_SIZE);
if (new == NULL) {
perror("malloc(buffer)");
exit(EXIT_FAILURE);
}
struct pkt *data;
data = malloc(sizeof(struct pkt) * MAX_SIZE);
if (data == NULL) {
perror("malloc(data)");
exit(EXIT_FAILURE);
}
new->data = &data;
new->a = 0;
new->b = 0;
return new;
}
struct pkt *new_pkt(char *data, int seq) {
struct pkt *pkt;
pkt = malloc(sizeof(struct pkt));
if (pkt == NULL) {
perror("malloc(pkt)");
exit(EXIT_FAILURE);
}
pkt->buf = malloc(sizeof(char) * MAX_CHAR);
if (pkt->buf == NULL) {
perror("malloc(pkt->buf)");
exit(EXIT_FAILURE);
}
strncpy(pkt->buf, data, MAX_CHAR);
pkt->seq = seq;
return pkt;
}
void add_pkt(struct pkt *pkt, struct buffer *buf, int i) {
buf->data[i] = pkt; //segmentation fault
}
int main() {
struct buffer *my_buffer = new_buffer();
struct pkt *pkt;
int i;
for(i=0; i<MAX_SIZE; ++i) {
pkt = new_pkt(string, i);
add_pkt(pkt, my_buffer, i);
printf("[%d]", i);
}
return 0;
}
change
struct pkt *data;
data = malloc(sizeof(struct pkt) * MAX_SIZE);
if (data == NULL) {
perror("malloc(data)");
exit(EXIT_FAILURE);
}
new->data = &data;
to
new->data = malloc(sizeof(struct pkt*) * MAX_SIZE);
if (new->data == NULL) {
perror("malloc(new->data)");
exit(EXIT_FAILURE);
}
struct pkt *data; is a local variable, saving its address and using it after the scope ends, is undefined behaviour. Also you want a memory area where you can save some struct pkt*s and not struct pkts.
Since you are not freeing anything, you have a big memory leak.

Assigning pointer member of a struct to null

I am having some difficulty assigning a pointer inside a struct to null. Since pointers are pass by value, I can't find an easy way to do this. Maybe its been a long day and I can''t think straight. Anyways, here is my code:
void
init_wordrec (wordrec *rec)
{
if ((rec = (wordrec *) malloc(sizeof(wordrec))) == NULL) {
perror("Malloc failed");
exit(1);
}
rec->word = NULL;
rec->hits = 0;
rec->nxt_wd = NULL;
}
Here is the wordrec struct:
typedef struct wordrec
{
char *word;
int hits;
struct wordrec *nxt_wd;
} wordrec;
I want the actual word pointer to point to null, unfortunately my attempts have only caused gcc to complain loudly.
EDIT: Here is a method where I pass in word struct.
void
add_word (char *word, wordrec *head)
{
wordrec *iter = head;
wordrec *tmp;
if (iter->word == NULL) { //This should be NULL but is not
if ((iter->word = (char *) malloc((strlen(word) + 1) * sizeof(char))) == NULL) {
perror("Malloc failed");
exit(1);
}
strncpy(iter->word, word, strlen(word) + 1);
iter->hits++;
init_wordrec (iter->nxt_wd);
} else if (strcmp(iter->word, word) < 0) {
init_wordrec (tmp);
if ((tmp->word = (char *) malloc((strlen(word) + 1) * sizeof(char))) == NULL) {
perror("Malloc failed");
exit(1);
}
strncpy(tmp->word, word, strlen(word) + 1);
tmp->hits++;
tmp->nxt_wd = head;
head = tmp;
} else if (strcmp(iter->word, word) > 0) {
add_word (word, iter->nxt_wd);
} else {
iter->hits++;
}
}
Main:
int
main()
{
wordrec head;
char word1[] = "Hello";
init_wordrec (&head);
add_word(word1, &head);
return 0;
}
Did you mean something like this:
void init_wordrec(wordrec **rec)
{
if ((*rec = (wordrec *) malloc(sizeof(wordrec))) == NULL) {
perror("Malloc failed");
exit(1);
}
(*rec)->word = NULL;
(*rec)->hits = 0;
(*rec)->nxt_wd = NULL;
}
....
wordrec *wr;
init_wordrec(&wr);
Assignment goes the other way — you assign a value, such as NULL, to a variable, such as rec->word.
You could pass a double pointer to the function:
void
init_wordrec (wordrec **rec)
{
if ((*rec = (wordrec *) malloc(sizeof(wordrec))) == NULL) {
perror("Malloc failed");
exit(1);
}
(*rec)->word = NULL;
(*rec)->hits = 0;
(*rec)->nxt_wd = NULL;
}
/* ... */
wordrec *wr = 0;
init_wordrec(&wr);
but since you're allocating in the function (so you're just going to throw away the value passed in) making it return the new record usually simplifies the code:
wordrec*
init_wordrec(void)
{
wordrec *rec = malloc(sizeof(*rec));
if (rec == NULL) {
perror("Malloc failed");
exit(1);
}
rec->word = NULL;
rec->hits = 0;
rec->nxt_wd = NULL;
return rec;
}
/* ... */
wordrec *wr = init_wordrec();
You shouldn't cast the result of malloc; it will make the code compile even if you fail to include its prototype, but will fail badly at runtime.
A simpler option would be:
void init_wordrec (wordrec *rec)
{
rec->word = NULL;
rec->hits = 0;
rec->nxt_wd = NULL;
}
which allows your code in main to remain unchanged:
int main()
{
wordrec head;
char word1[] = "Hello";
init_wordrec (&head);
Another advantage of this is that users of wordrec have the option to use automatic allocation or dynamic allocation (whereas the other proposed answers force dynamic allocation to be used).

Resources