Segmentation Fault: double free or corruption (fast top) - c

I've a problem when I run this piece of code: a Segmentation Fault that appears during the free instruction of percorso. I cannot find the problem.
void ricerca(char nome[], struct node *radice, char percorso[], struct stringhe **indice) {
struct node *punt = radice;
int dim = len(percorso);
char *prov = NULL;
if (dim > 0) {
prov = malloc(2 * dim * sizeof(char));
prov[0] = '\0';
strcpy(prov, percorso);
free(percorso); //--------------------->here the SegFault
}
struct stringhe *nuovo = NULL;
int i = 0, fine = 0;
char *perc_orig = NULL;
if (punt != NULL) {
if (punt->array != NULL) {
dim = len(prov) + len(punt->nome) + 2;
percorso = malloc(dim * sizeof(char));
percorso[0] = '\0';
if (prov!=NULL)
strcpy(percorso, prov);
strcat(percorso, "/");
strcat(percorso, punt->nome);
perc_orig = malloc(dim * sizeof(char));
for (i = 0; i < N; i++) {
if (punt->array->vet[i] != NULL) {
perc_orig[0] = '\0';
strcpy(perc_orig, percorso);
ricerca(nome, punt->array->vet[i], perc_orig,indice);
}
}
free(perc_orig);
}
if (strcmp(nome,punt->nome) == 0) {
free(percorso);
dim = len(prov) + len(punt->nome) + 2;
percorso = malloc(dim * sizeof(char));
inizializza(percorso, dim);
if (prov != NULL)
strcpy(percorso, prov);
strcat(percorso, "/");
strcat(percorso, punt->nome);
nuovo = malloc(sizeof(struct stringhe));
nuovo->next = NULL;
nuovo->str = malloc(dim * sizeof(char));
inizializza(nuovo->str, dim);
strcpy(nuovo->str, percorso);
nuovo->next = (*indice);
*indice = nuovo;
}
while (punt->chain != NULL && fine == 0) {
ricerca(nome, punt->chain,prov, indice);
fine = 1;
if (prov!=NULL)
free(prov);
}
}
}
The len function is like strlen, but the difference is that I've made it myself.
the context is:
void find(char nome[], struct node *radice) {
char *perc = NULL;
struct stringhe **inizio = NULL;
inizio = malloc(sizeof(struct stringhe*));
*inizio = NULL;
int i = 0;
for (i = 0; i < N; i++) {
if (radice->array->vet[i] != NULL) {
perc = NULL;
ricerca(nome, radice->array->vet[i], perc, inizio);
}
}
if (*inizio != NULL) {
insertion(inizio);
stampap(*inizio);
} else
printf("no\n");
}
And the data structures:
struct tab {
struct node *vet[64];
};
struct node {
char nome[255];
int num;
int tipo;
char *dati;
struct tab *array;
struct node *chain;
};

This is really weird:
if (some condition)
free(percorso);
Later on we have:
perc_orig = malloc(dim*sizeof(char));
for(something){
if(something){
ricerca(nome,punt->array->vet[i],perc_orig,indice);
}
}
free(perc_orig);
If that if conditions happens, perc_orig will be freed twice. Kaboom.
I think your problem is you think that ricerca(..., char percico[], ...) copies percico. It doesn't; it's really ricerca(..., char *percico, ...) so you ended up freeing the memory twice.

the sizing for the char arrays needs to allow for the trailing NUL ('\0') character.
ALL fields that are referenced by strcpy() and similar functions need to have ALL source character arrays NUL terminated.
The code does not seem to be allocating enough room for those trailing NUL bytes NOR terminating every character array with a NUL char.

Segmentation fault occurs when you initialize a character pointer to NULL and try to point it to a not null value
For example,
char *a=NULL;
a='a';
Will cause segmentation fault. To avoid this you can try to initialize as,
char *a;
a='a';

Related

How can I access the tree in my printpostroder function?

This is my tree struct :
typedef struct quad
{
struct quad *child[4];
char *names;
} quad;
and I need to build it then print it in postorder
but I can't access the memory for the tree in my printpostorder function :
void printpostorder(quad * tree)
{
if (tree->names[0] == 'G') {
printpostorder(tree->child[0]);
printpostorder(tree->child[1]);
printpostorder(tree->child[2]);
printpostorder(tree->child[3]);
printf("%s", tree->names);
}
else {
printf("%s", tree->names);
}
}
I can access it before calling this function in the main function.
int main(void){
int n = 0;
int size;
quad * t;
char * str1 = (char *)malloc(MAX * sizeof(char));
printf("Enter name: ");
scanf("%s", str1);
size = strlen(str1);
t = build_preorder_tree(str1,t,&n,size);
printpostorder(t);
}
here is the build tree function, basically we have to build from preorder, then print out the post order.
quad* build_preorder_tree(char *s_r, quad * tree, int * index_ptr,int size){
char c;
int s = 0;
int index = *index_ptr;
c = s_r[index];
char d = ']';
char * ptr = (char *)malloc(MAX * sizeof(char));
char * ptr1;
if(index == size){
return;
}
tree = malloc(sizeof(quad*));
tree -> names = (char *)malloc(MAX * sizeof(char));
if(c == 'G') {
tree->names = "G";
(*index_ptr)++;
tree->child[SW] = build_preorder_tree(s_r, tree->child[SW],index_ptr,size);
tree->child[SE] = build_preorder_tree(s_r, tree->child[SE],index_ptr,size);
tree->child[NW] = build_preorder_tree(s_r, tree->child[NW],index_ptr,size);
tree->child[NE] = build_preorder_tree(s_r, tree->child[NE],index_ptr,size);
}
if(c == 'W') {
tree->names = "W";
(*index_ptr)++;
}
if(c == 'B') {
strcpy(ptr,s_r);
ptr1 = strtok(ptr+index,"]");
strncat(ptr1,&d,1);
s = strlen(ptr1);
(*index_ptr)= (*index_ptr) + s;
tree->names = ptr1;
}
return tree;
}
And when I call the printpostorder(t), a seg fault occurred at first call of
if (tree->names[0] == 'G')
I tried to access the tree before the printpostorder is call, and I was able to access every element of the tree

How to fix copy of struct to array of structs segfault

I have the following two structs:
typedef struct {
char* key;
char* value;
} kvpair;
typedef struct {
kvpair ** array;
size_t length;
} kvarray;
And I want to copy new key and value pairs to the kvarray. I use realloc to allocate memory for each new item to be added to the kvpair array but struggling to work out how to copy the key and value.
If I do it like this:
kvs->array resized using realloc
// *** get segfault here!!! how to fix ***
kvs->array[kvs->length]->key = key;
kvs->array[kvs->length]->value = value;
But if I allocate memory separately for a kvpair* and do this way:
kvpair* kvp = malloc(sizeof(kvpair));
// copy key and value
// This below then works
kvs->array[kvs->length] = kvp;
// but there is a memory leak - or seems to be double allocation of memory for same thing
How to do this correctly?
The code is below (see // * get segfault here!!! how to fix * comment)
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct {
char* key;
char* value;
} kvpair;
typedef struct {
kvpair ** array;
size_t length;
} kvarray;
kvarray * readKVs(const char** array, size_t length);
void freeKVs(kvarray * pairs);
int main() {
const char* things[] = { "wood=brown\n", "brick=red\n",
"grass=green", "hedge=green", "leaf=green" };
const size_t sz = sizeof(things) / sizeof(things[0]);
kvarray* kvs = readKVs(things, sz);
freeKVs(kvs);
}
kvarray * readKVs(const char** array, size_t length) {
kvarray* kvs = NULL;
for (size_t i = 0; i < length; ++i) {
const char* line = array[i];
if (kvs == NULL) {
kvs = malloc(sizeof(kvarray));
kvs->length = 0;
kvs->array = NULL;
}
char * found = strchr(line, '=');
if (found == NULL) {
// skip to next line
continue;
}
size_t len = strlen(line);
size_t pos = found - array[i];
char* value = NULL;
if (len > (pos + 1)) {
// non-blank value
// length of value is len - pos
value = malloc(len - (pos + 1));
strncpy(value, &line[pos + 1], (len - (pos + 1)) - 1);
// null terminate string
value[len - (pos + 1) - 1] = '\0';
printf("value:'%s'\n", value);
}
char* key = malloc(found - line + 1); // +1 for null terminator
strncpy(key, line, pos);
// remember strncpy bug!
key[found - line] = '\0'; // ensure null termination.
printf("key:'%s', length=%lu\n", key, strlen(key));
/*
// if I allocate an individual pair, then I am duplicating memory so should have to do this below
kvpair* kvp = malloc(sizeof(kvpair));
//kvpair kvp = {NULL, NULL};
printf("about to assign kvs->key = key\n");
kvp->key = key;
printf("about to assign kvs->value = value\n");
kvp->value = value;
*/
kvs->array = realloc(kvs->array, (kvs->length + 1) * sizeof(kvpair*));
// I want to be able to do this 2 lines below - but crashes
// *** get segfault here!!! how to fix ***
kvs->array[kvs->length]->key = key;
kvs->array[kvs->length]->value = value;
kvs->length++;
printf("kvs->length now=%lu\n", kvs->length);
}
return kvs;
}
void freeKVs(kvarray * pairs) {
if (pairs == NULL) {
return;
}
for (size_t i = 0; i < pairs->length; ++i) {
free(pairs->array[i]->key);
free(pairs->array[i]->value);
free(pairs->array[i]);
}
free(pairs);
}
When you do
kvs->array = realloc(kvs->array, (kvs->length + 1) * sizeof(kvpair*));
the contents of the new memory allocated will be indeterminate, it's not initialized. That means the next line
kvs->array[kvs->length]->key = key;
you will dereference an invalid pointer kvs->array[kvs->length]. That of course will lead to undefined behavior.
The solution is of course to make kvs->array[kvs->length] point somewhere valid, for example by doing
kvs->array[kvs->length] = malloc(sizeof(kvpair));

strcpy : how can i not copy \n [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
struct configurations *read_file(char * file_name)
{
FILE *f = fopen(file_name ,"r");
if(!f)
{
printf("**********Unable to open config.txt*********");
return NULL;
}
int i, prev, count;
char *line = NULL, buff[480] = {'\0'};
size_t len;
struct configurations *config = (struct configurations *) malloc(sizeof(struct configurations));
while (getline(&line,&len,f) != -1)
{
if(!strncmp("SERVERPORT = ",line,strlen("SERVERPORT = "))){
config->server_Port = atoi(strstr(line, " = ")+3);
}
else if(!strncmp("SCHEDULING = ",line,strlen("SCHEDULING = "))){
strcpy(config->sched,strstr(line, " = ") + 3);
}
By subctracting 1 from the length.
There are multiple simple and obvious improvements to your code
You should always check the return value before using from strstr().
strlen("SERVERPORT = ") is a very ugly way of writing 12, inefficient too.
You should use a little bit more white spaces to make the code readable.
Don't cast the return value of malloc() it only makes it more difficult to read and might hide a bug if you forget to include stdlib.h.
ALWAYS check if malloc() returned NULL before dereferencing the pointer.
Split every line at =, remove all surrounding white spaces from the 2 resulting values and then check which variable it is and assign the corresponding value.
As it is your code will fail if SERVERPORT=1234 for example, and even if it's ugly and spaces around the = operator are better, both should be valid unless of course you explicitly want the spaces.
Also by removing surrounding white spaces you ensure that any '\n' that was read by getline() will be removed from the value.
This is a quick API a wrote just now to show you how I would do it, of course every one has their own taste and ways to do things, but I hope it helps figuring out your mistakes
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
struct KeyValue {
char *key;
char *value;
};
struct KeyFile {
size_t size;
struct KeyValue *entries;
size_t count;
};
static struct KeyFile *
keyfile_new(void)
{
struct KeyFile *kf;
kf = malloc(sizeof(*kf));
if (kf == NULL)
return NULL;
kf->entries = malloc(10 * sizeof(*kf->entries));
if (kf->entries == NULL) {
kf->size = 0;
} else {
kf->size = 10;
}
kf->count = 0;
return kf;
}
static int
keyfile_add_value(struct KeyFile *kf, const char *const key, const char *const value)
{
struct KeyValue *entry;
if (kf->count + 1 >= kf->size) {
void *pointer;
pointer = realloc(kf->entries, (kf->size + 10) * sizeof(*kf->entries));
if (pointer == NULL)
return -1;
kf->entries = pointer;
kf->size += 10;
}
entry = &kf->entries[kf->count++];
entry->key = strdup(key);
entry->value = strdup(value);
return 0;
}
static void
keyfile_free(struct KeyFile *kf)
{
for (size_t i = 0 ; i < kf->count ; ++i) {
struct KeyValue *entry;
entry = &kf->entries[i];
free(entry->key);
free(entry->value);
}
free(kf->entries);
free(kf);
}
static struct KeyFile *
keyfile_read(const char *const path)
{
FILE *file;
struct KeyFile *kf;
size_t length;
char *line;
line = NULL;
length = 0;
file = fopen(path, "r");
if (file == NULL)
return NULL;
kf = keyfile_new();
if (kf == NULL)
return NULL;
while (getline(&line, &length, file) > 0) {
char *op;
char *key;
char *value;
op = strchr(line, '=');
if (op == NULL) {
fprintf(stderr, "malformed line!\n");
} else {
*op = '\0';
key = line;
while (isspace((unsigned char) *key) != 0)
++key;
value = op + 1;
op -= 1;
while (isspace((unsigned char) *op) != 0)
*(op--) = '\0';
while (isspace((unsigned char) *value) != 0)
value += 1;
op = value + strlen(value) - 1;
while (isspace((unsigned char) *op) != 0)
*(op--) = '\0';
if (keyfile_add_value(kf, key, value) != 0)
goto error;
}
}
fclose(file);
free(line);
return kf;
error:
keyfile_free(kf);
fclose(file);
free(line);
return NULL;
}
static void
keyfile_display(const struct KeyFile *const kf)
{
for (size_t i = 0 ; i < kf->count ; ++i) {
const struct KeyValue *entry;
entry = &kf->entries[i];
fprintf(stdout, "/%s/ => /%s/\n", entry->key, entry->value);
}
}
You could improve this to add lookup functions, to find specific values in the settings file. And you can make it a standalone library to use it in many projects too.

Memory leak in a recursive function in c

I need some help with memory leak in my C program. The following function searches a radix trie to find a word with a given number. It allocates some memory in every recursive call and I don't know how to sort it out so that the blocks allocated aren't lost. Please help.
char *substring(char *str, int position, int length) {
int c = 0;
char *sub = malloc(length*(sizeof(char))+1);
while (c < length) {
sub[c] = str[position + c];
c++;
}
return sub;
}
void prev(int w, int start, int end) {
char *newWord = "";
bool found = false;
void prevRec(struct tNode *t,
int w, int start, int end, char *soFar, int prevLength) {
if (t != NULL) {
char *updatedWord = malloc(strlen(soFar) + strlen(t->word));
strcpy(updatedWord,soFar);
strcat(updatedWord,t->word);
printf("%s\n", updatedWord);
int length = strlen(t->word);
if (t->count == w) {
found = true;
if ((start > -1) && (end <= strlen(updatedWord))) {
newWord = updatedWord;
} else {
newWord = "";
}
} else {
struct tNode *tmp = t->child;
struct tNode *tmp1 = NULL;
while ((tmp != NULL) && (!found)) {
prevRec(tmp,w,start,end,updatedWord,length);
tmp1 = tmp;
tmp = tmp->brother;
updatedWord = substring(updatedWord, 0, strlen(updatedWord) - prevLength);
}
}
}
}
prevRec(root,w,start,end,newWord,0);
printf("%s\n",newWord);
if (strlen(newWord) == 0) printf("ignored");
else {
char *tmp = substring(newWord,start,end - start + 1);
insert(tmp);
free(tmp);
}
You must free what you've allocated. In your case you could to sth. like that: replace
updatedWord = substring(updatedWord, 0, strlen(updatedWord) - prevLength);
by
char *sub = substring(updatedWord, 0, strlen(updatedWord) - prevLength);
free( updatedWord );
updatedWord = sub;
and add another
free( updatedWord );
as last line of your if( t != NULL ) block.
Besides as #Eregith has already mentioned in his comment, the '+1' for NULL is missing in the length you are allocating. And you should also add some error checking, as malloc() may return NULL

Having trouble when allocating memory when passing a double pointers address into a triple pointer

I'm creating a double pointer and sending in the address to allocate memory, which requires a triple pointer. Also, i am creating single pointers (goals and assists) and sending their addresses to allocate memory, which requires double pointers. I think the problem lies in allocation of memory, but i cant figure it out. I keep seg faulting whenever i run the readLinesFromFile function. It does not segfault when I try running allocateMemory function by itself. The problem could also be in the readLinesFromFile function
int main (int argc, char **argv)
{
int numPlayers = 0;
if (argc != 3)
{
printf("Missing text file");
return 0;
}
char **playerNames;
int *goals, *assists;
FILE *filePtr = fopen(argv[1],"r");
if(filePtr == NULL)
{
printf("\nFile is empty");
return 0;
}
numPlayers = countLinesInFile(filePtr);
allocateMemory(&goals,&assists,&playerNames,numPlayers);
readLinesFromFile(filePtr,goals,assists,playerNames,numPlayers);
}
void allocateMemory(int **goals, int **assists, char *** names, int size)
{
int i = 0;
*goals = malloc(MAX_NAME * sizeof(int));
*assists = malloc(MAX_NAME * sizeof(int));
*names = malloc(MAX_NAME * sizeof(char*));
for (i = 0; i < size; i++)
{
(names[i]) = malloc(MAX_NAME * sizeof(char*));
}
}
void readLinesFromFile(FILE *fptr, int *goals, int *assists, char **names, int numLines)
{
int i = 0, j = 0, x = 0;
char players[MAX_LINE];
char *tokenPtr;
fptr = fopen(INPUT,"r");
for(i = 0; i < numLines; i++)
{
fgets(players,MAX_LINE, fptr);
tokenPtr = strtok(players," ");
strcpy((*(names+i)), tokenPtr);
while (tokenPtr != NULL)
{
tokenPtr = strtok(NULL," ");
if (x = 0)
{
goals[i] = atoi(tokenPtr);
x = 1;
}
else
{
assists[i] = atoi(tokenPtr);
x = 0;
}
}
}
}
Assuming MAX_NAME is the maximum length of a player's name, this should work:
void AllocateMemory(char *** pppNames, int ** ppGoals, int ** ppAssists, size_t sizePlayersMax)
{
*pppNames = malloc(sizePlayersMax * sizeof **pppNames);
*ppGoals = malloc(sizePlayersMax * sizeof **ppGoals);9
*ppAssists = malloc(sizePlayersMax * sizeof **ppAssists);
{
size_t sizePlayersCount = 0;0
for (; sizePlayersCount < sizePlayersMax; ++sizePlayersCount)
{
(*pppNames)[sizePlayersCount] = calloc(MAX_NAME + 1, sizeof *((*pppNames)[sizePlayersCount]));
}
}
}
To prevent the app from overwriting memory in case of really long player names you might like to change this line:
strcpy((*(names+i)), tokenPtr);
to become:
if (tokenPtr)
strncpy((*(names+i)), tokenPtr, MAX_NAME);
This would truncate the player names stored to a maximum of MAX_NAME characters. The latter is the size AllocateMemory() use minus 1. This one spare character is needed for the 0/NUL to terminate the character-array so it could be used as a "string".
Finally also this is dangerous:
while (tokenPtr != NULL)
{
tokenPtr = strtok(NULL," ");
if (x = 0)
{
Better do like this:
while (NULL != (tokenPtr = strtok(NULL," ")))
{
if (x = 0)
{

Resources