I'm writing a program in C that creates and tries to allocate the struct array. It manages to allocate the first block of memory and i successfully wrote the values on it but when i try to allocate a second time i get a error related to corrupted heap and "Invalid address specified to RtlValidateHeap".
here is my code (sorry for some parts in portuguese):
structs.h:
typedef struct vendedor
{
unsigned int numero;
char * nome;
float salario;
uint8_t comissao;
} VENDEDOR;
functions.h
extern vendedor * vende = (vendedor *)malloc(0);
extern unsigned int vende_sz = 0;
char * receberString()
{
int size = 0;
char temporary;
char * string = NULL;
string = (char *)malloc(size);
while (true)
{
scanf("%c", &temporary);
string = (char *)realloc(string, (size + 1) * sizeof(char));
if (temporary == '\n')
{
string[size] = '\0';
return string;
}
else
string[size] = temporary;
size++;
}
}
vendedor * alocarVende()
{
vendedor * tmpVende = (vendedor *)
realloc(vende, sizeof(vendedor)* vende_sz+1); //crashes here at second time
if (tmpVende == NULL)
{
printf("\nfailed to allocate.\n");
//free(tmpVende);
exit(-1);
}
else
{
vende = tmpVende;
//commented due to problems related
//free(tmpVende);
vende_sz++;
return vende;
}
}
main.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
#include "structs.h"
#include "functions.h"
int main() {
login();
return 0;
}
bool login()
{
if (vende_sz == 0)
{
vende = alocarVende();
vende[0].salario = 666.66;
vende[0].numero = 1;
vende[0].comissao = 22;
vende[0].nome = receberString(); //dynamically allocates memory for a string using realloc
printf("%s", vende[0].nome);
vende = alocarVende();
vende[1].nome = receberString(); //dynamically allocates memory for a string using realloc
printf("%s", vende[1].nome);
return true;
}
}
any tips or help? I tried commenting free and some other things but still the same problem, thanks.
Edit: added more bits of code.
vende = tmpVende;
free(tmpVende);
This is precisely the same as:
vende = tmpVende;
free(vende);
Since vede and tmpVende are pointers with the same value, passing either one to free does the same thing -- frees the underlying thing they both point to.
vende[1].nome = receberString();
Thus this is a use after free that corrupts memory.
Also, you have this:
sizeof(vendedor)* vende_sz+1
Which doesn't do what you want because multiplication has higher precedence than addition.
Related
When I try to free my struct, the program crashes because of a segfault. Inspecting the program with valgrind I have found:
==9761== Invalid free() / delete / delete[] / realloc()
==9761== at 0x484827F: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9761== by 0x109242: destroyHashTable (hashtable.c:38)
==9761== by 0x10942E: main (hashtable_main.c:17)
==9761== Address 0x1ffefffa70 is on thread 1's stack
==9761== in frame #2, created by main (hashtable_main.c:7)
I cannot really say anything more useful than having no idea, how to solve it. The crash happens during the free(ht) in destroyHashTable(ht) in hashtable.c. What am I doing wrong?
Below the code hashTable_main.c:
#include <stdio.h>
#include <stdlib.h>
#include "hashtable.h"
int main() {
hashTable* ht = NULL;
initHashTable(&ht);
int totalColCount = 0;
totalColCount += addHashTableEntry(&ht, "PRPR2");
destroyHashTable(&ht);
return EXIT_SUCCESS;
}
hashtable.c:
#include <stdlib.h>
#include <stdio.h>
#include "hashtable.h"
/* private internal API */
int hash_funktion(char *string);
hashtableEntry* createTableEntry(char* newKey) ;
/* end of private internal API */
int hash_funktion(char *string) {
unsigned int hash_adresse;
unsigned char *pointer;
hash_adresse = 0;
pointer = (unsigned char *) string;
while(*pointer != '\0') {
hash_adresse = 19 * hash_adresse + *pointer;
pointer++;
}
return hash_adresse % MAX_HASH;
}
hashtableEntry* createTableEntry(char* newKey) {
hashtableEntry* e = (hashtableEntry*) malloc (sizeof(hashtableEntry));
e->hashKey = newKey;
return e;
}
void initHashTable(hashTable* ht) {
ht = (hashTable*) malloc (sizeof (struct hashTable));
ht->table = (hashtableEntry*) malloc (MAX_HASH * sizeof (hashtableEntry));
}
void destroyHashTable(hashTable* ht) {
if (ht) {
free(ht);
ht = NULL;
}
}
int addHashTableEntry(hashtableEntry* ht, char* keyValue) {
hashtableEntry *e = createTableEntry(keyValue);
int colCounter = 0;
int hashValue = hash_funktion(keyValue);
if (ht[hashValue].hashKey == NULL) {
ht[hashValue] = *e;
return 0;
} else {
int newVal = (hashValue + 1) % MAX_HASH;
colCounter++;
while (ht[newVal].hashKey != NULL && newVal != hashValue ) {
newVal = (newVal + 1) % MAX_HASH;
colCounter++;
}
if (newVal != hashValue) {
ht[newVal] = *e;
return colCounter;
} else {
return -1;
}
}
}
bool searchValue(hashtableEntry* ht, char* searchValue) {
for (int i = 0; i < MAX_HASH; i++)
{
if(ht[i].hashKey == searchValue) {
return true;
}
}
return false;
}
and hashtable.h:
#pragma once
#define MAX_HASH 20
#include <stdbool.h>
typedef struct hashtableEntry {
char* hashKey;
} hashtableEntry;
typedef struct hashTable {
hashtableEntry* table;
int elemCount;
} hashTable;
void initHashTable(hashTable* ht);
void destroyHashTable(hashTable* ht);
int addHashTableEntry(hashtableEntry* ht, char* keyValue);
bool searchValue(hashtableEntry* ht, char* searchValue);
There never was a hashtable to begin with. The issue lies in initHashTable. It should be accepting a double pointer since it is given a pointer to a pointer it should initialize. The reason it can segfault despite the check in destroyHashTable is that the pointer is left uninitialized and may be non-zero at the start of program execution.
void initHashTable(hashTable** ht) {
*ht = (hashTable*) malloc (sizeof (struct hashTable));
(*ht)->table = (hashtableEntry*) malloc (MAX_HASH * sizeof (hashtableEntry));
}
You may find it easier to instead return the newly created hash table. This better expresses that initHashTable is giving you a new hashTable * value.
hashTable *initHashTable() {
hashTable *ht = (hashTable *) malloc (sizeof (struct hashTable));
ht.table = (hashtableEntry *) malloc (MAX_HASH * sizeof (hashtableEntry));
return ht;
}
There are also a bunch of other places where pointers are not handled correctly.
void doThing(Foo *foo) {
// This changes foo, but not the data foo points to.
foo = something;
// This changes the data foo points to
*foo = someOtherThing;
}
void doStuff() {
Foo *foo;
// This is incorrect since it creates a double pointer. doThing would need to
// be defined as "void doThing(Foo **foo)" to be correct.
doThing(&foo);
// Instead we can just pass the existing pointer
doThing(foo);
// We only need to create a reference if the value does not start out as a pointer
Foo bar;
doThing(&bar);
}
works:
struct data{
int val;
};
int main(void){
struct data *var[2];
(*var)->val = 6;
printf("%d\n", (*var)->val);
return 0;
}
segfault:
struct data{
int val;
};
int main(void){
struct data **var = malloc(3 * sizeof(struct data));
(*var)->val = 6; // <- crash
printf("%d\n", (*var)->val);
return 0;
}
can someone explain why segfault appears and give me an working example with minimal changes to the segfault code that i can understand pls.
The pointer is not malloc'ed, you are dereferencing an invalid pointer because your array is an array of poitners, and it's elements are not pointing to valid memory.
Try this
#include <stdio.h>
#include <stdlib.h>
struct data
{
int val;
};
int main(void)
{
struct data *var[2];
/* You need to malloc before dereferencing `var[0]` */
var[0] = malloc(sizeof(var[0][0]));
if (var[0] != NULL)
{
var[0]->val = 6;
printf("%d\n", var[0]->val);
free(var[0]);
}
return 0;
}
also, using (*var)->val = 6 is absolutely unnecessary and confusing.
In the second case, you should also do almost the same thing, except that the array of pointers is a pointer to an array of poitners and hence needs malloc() too, so your second example accidentally works because there is enough memory malloc()ed but it's also wrong, you should do it this way
#include <stdio.h>
#include <stdlib.h>
struct data
{
int val;
};
int main(void)
{
struct data **var;
var = malloc(2 * sizeof(var[0]));
if (var == NULL)
return -1;
/* You need to malloc before dereferencing `var[0]` */
var[0] = malloc(sizeof(var[0][0]));
if (var[0] != NULL)
{
var[0]->val = 6;
printf("%d\n", var[0]->val);
free(var[0]);
}
free(var);
return 0;
}
i have a problem with the initialization of the values inside the first dynamic array of pointers
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char*** GetIndexes()
{
int n = 0;
char ***index;
printf("please insert the number of words you want to add to dictionary\n");
scanf("%d", &n);
index = (char***)calloc(n, sizeof(char));
if (index == NULL)
{
printf("allocation Failed");
return;
}
return index;
}
char** GetDefinitions()
{
int n = 0;
char **definition;
printf("please insert the number of defintions you want to add to the word\n");
scanf("%d", &n);
definition = (char**)calloc(n+1, sizeof(char));
if (definition == NULL)
{
printf("allocation failed");
return;
}
return definition;
}
int main()
{
char *** dptr = GetIndexes();
if (dptr == NULL)
{
printf("memory Allocation failed");
}
int indexcount = sizeof(dptr) / sizeof(char),i;
for (i = 0; i < indexcount; i++)
{
printf("word number %d\n", i + 1);
*dptr[i] = GetDefinitions();
}
printf("%p",dptr);
}
i tried running the debugger in VS2013 and after i enter the number of defintions i want it crashed with this message:
Unhandled exception at 0x01103FB0 in ConsoleApplication1.exe: 0xC0000005: Access violation writing location 0x00000000.
i missed an allocation of something but i cant quite figure out what i missed,
thanks in advance
Your program is very broken
You allocate n char ***s but only request space for n chars and also do it for char **, to prevent this kind of mistake you may use the sizeof operator this way
char ***index;
index = calloc(n, sizeof(*index));
and
char **definition;
definition = calloc(n, sizeof(*definition));
and as you see casting calloc makes it harder and it's not necessary.
You have a return statement that doesn't return anything an GetIndexes() as well as one in GetDefinitions.
They should return NULL if you want to handle failure in the caller function
return NULL;
You erroneously use the sizeof operator to determine the number of char *** pointer allocated in
int indexcount = sizeof(dptr) / sizeof(char)
this will be either 4 or 8 depending on the architecture i.e. the size of a pointer divided by 1 sizeof(char) == 1 always.
You can't compute that value, you simply have to keep track of it. The size
You dereference the triple pointer twice and try to assign a double pointer to it
*dptr[i] = GetDefinitions();
here the operator precedence is also an issue, but regardless of that, this is wrong, may be what you meant was
dptr[i] = GetDefinitions();
This is not going to make your program crash, but it's certainly important to free all malloced pointers before exiting the program.
Here is a suggestion for your code to work, ignore it's purpose since it's not clear what you are trying to do
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char ***GetIndexes(unsigned int *count)
{
char ***index;
printf("please insert the number of words you want to add to dictionary > ");
scanf("%u", count);
index = calloc(*count, sizeof(*index));
if (index == NULL)
{
printf("allocation Failed");
return NULL;
}
return index;
}
char **GetDefinitions(unsigned int *count)
{
char **definition;
printf("please insert the number of defintions you want to add to the word > ");
scanf("%u", count);
definition = calloc(*count + 1, sizeof(*definition));
if (definition == NULL)
{
printf("allocation failed");
return NULL;
}
return definition;
}
int main()
{
unsigned int indexCount, i;
char ***dptr = GetIndexes(&indexCount);
if (dptr == NULL)
{
printf("memory Allocation failed");
}
for (i = 0; i < indexCount; i++)
{
unsigned int definitionsCount;
printf("Word number %u\n", i + 1);
dptr[i] = GetDefinitions(&definitionsCount);
if (dptr[i] != NULL)
{
/* use dptr[i] here or maybe somewhere else, but when you finish */
free(dptr[i]);
}
}
printf("%p", dptr);
/* now if you are done using dptr */
free(dptr);
return 0;
}
As already mentioned in the comment this is a very bad idea and just using double pointers is good here. But the below fixes should be done if you want to use pointers to allocate memory
index = calloc(n, sizeof(char));
should be
index = calloc(n, sizeof(char **));
and
definition = calloc(n+1, sizeof(char));
should be
definition = calloc(n+1, sizeof(char *));
I am a beginner in C. Below is my scenario - I have created a pointer variable in main function and it has been passed on to several functions(in this example 2 levels). And one of the functions frees it up. Now I need to have check in Main to see whether the pointer is freed or not, that means i need to setup the value of &str in main() to point to NULL. Not sure my approach is right here. Any help would be much appreciated
void func2(char *str)
{
free(str);
}
void func1(char *str)
{
func2(str);
}
int main()
{
char *str;
str=(char *) malloc(10);
func1(str);
if(str){ do something; } // if condition to check whether str is freed
}
#include <stdio.h>
#include <stdlib.h>
func2(char **str)
{
free(*str); //free
*str = NULL; //Set to NULL
}
func1(char **str) //func1 receives as **
{
func2(str); //Pass pointer to func2()
}
int main()
{
char *str = NULL;
str=(char *) malloc(10);
func1(&str); //Pass Address of pointer to func1()
if(str) //Check for NULL
{
printf("\n Not - Freed...\n");
}
else
{
printf("\n Freed...\n");
}
return 0;
}
In C all are pass by value. I suggest to study http://www.cs.fsu.edu/~myers/cgs4406/notes/pointers.html for understanding of this.
You could try something like this - first redefine malloc and free (track.h)
#ifndef track_h
#define track_h
extern void* trackmalloc(size_t size);
extern void trackfree(void* array);
extern void trackismalloc(void* array);
#define malloc trackmalloc
#define free trackfree
#endif
Then for every piece of code that uses malloc and free, replace #include with #include "track.h"
#include <stdlib.h>
#include <stdio.h>
#include "track.h" /* was <malloc.h> */
// A function which has a 20% chance of freeing the pointer
void twentypercent(char* array)
{
if (rand() < (RAND_MAX / 5))
free(array);
}
int main(int argc, char* argv[])
{
char* list = malloc(256);
int ii;
for (ii = 0; ii < 10; ++ii)
twentypercent(list);
if (trackismalloc(list)
printf("Not freed yet");
return 0;
}
Now define track.c. This will only free memory that has been allocated by by trackmalloc. If it was not allocated by trackmalloc, then it will report that the memory has already been freed.
#include <stdio.h>
#include <malloc.h>
#define TRACKER_MAX 2048
static void* tracker[TRACKER_MAX] = { 0 };
static int track_last = -1;
void* trackmalloc(size_t size)
{
// For simplicity, tracker will not be reused
tracker[++track_last] = malloc(size);
return tracker[track_last];
}
void trackfree(void* array)
{
// This will slow down as the list gets filled up.
// You will need a more efficient way of searching lists (possibly bsearch)
int tt;
for (tt = 0; tt < track_last; ++tt)
{
if (array == tracker[tt])
{
free(tracker[tt]);
tracker[tt] = 0;
break;
}
}
if (tt == track_last)
printf("%p already freed\n", array);
}
int trackismalloc(void* array)
{
// This will slow down as the list gets filled up.
// You will need a more efficient way of searching lists (possibly bsearch)
int tt, result = 0;
for (tt = 0; tt < track_last; ++tt)
{
if (array == tracker[tt])
{
result = 1;
break;
}
}
return result;
}
void func1(char** str) {
free(*str);
*str = NULL;
}
void func2(char** str) {
free(*str);
*str = NULL;
}
int main() {
char *str;
str = (char*) malloc(10);
func1(&str);
if (str) {
do something;
}
}
void func2(char **str)
{
free(*str);
*str = 0;
}
void func1(char **str)
{
func2(str);
}
int main()
{
char *str;
// I'd recommend using sizeof(type_you_want) * amount_of_elements instead of
// a constant number: -> malloc(sizeof(char) * 10);
str=(char *) malloc(10);
func1(&str); // You must pass the address of the pointer, because you want
// to change "WHAT IT POINTS TO", not "WHAT IS POINTED BY IT"
if(str){ do something; } // if condition to check whether str is freed
}
When you call a function in C, you pass a copy of those arguments, so you are passing a copy of that pointer (that copy still points to the same place, so you can change that place that it points to) but you want to change the pointer value, so you need to pass its address.
I have explained a little bit how pointers inside functions can be used in here
#include <stdio.h>
#include <stdlib.h>
void func2(char **str)
{
printf("%d %s\n",__LINE__,__func__);
free(*str);
*str = NULL;
}
void func1(char **str)
{
printf("%d %s\n",__LINE__,__func__);
func2(str);
}
char * allocaMem(char **ptr)
{
*ptr=(char *) malloc(sizeof(char)* 10);
if(!*ptr)
{
perror("");
}
else
{
return *ptr;
}
}
int main()
{
char *str = allocaMem(&str);
if (!str) {
printf("Error in malloc()\n");
return -1;
}
func1(&str);
if (str) {
printf("Memory Not freed\n");
} else {
printf("Memory freed\n");
}
}
I am learning pointer in c
i have written a small program , but i am getting segmentaion fault
i dont know where i am having the issue
please let me know the issue with the code , it is an array of pointers to string ,
which is in a pointer to structure .
# include <stdio.h>
#include <stdlib.h>
# include <string.h>
char *sum(char **sol) ;
char *summer_sum(char*** solcs) ;
int main()
{
char* datum ="teststring";
sum(&datum);
}
char *sum(char** sol)
{
printf("\n value is : %s",*sol);
summer_sum(&sol);
return "1" ;
}
char *summer_sum(char*** solcs)
{
int i=0;
typedef struct
{
char *asg[40];
}nlist;
nlist *n1;
for( i=0 ; i<= 38 ;i++)
{
n1->asg[i] = calloc(1,1*sizeof(*solcs));
strcpy(n1->asg[i],**solcs);
printf("\n %d value is : %s",i,n1->asg[i]);
}
return NULL;
}
n1 is used uninitialized:
n1->asg[i] = calloc(1,1*sizeof(*solcs));
On the other hand, if you want to allocate enough space for the use of strcpy, you must use strlen instead of sizeof
And you don't need a double or triple pointer, your code simplified:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void sum(char *sol);
char *summer_sum(char *solcs);
int main(void)
{
char *datum = "teststring";
sum(datum);
}
void sum(char *sol)
{
printf("\n value is : %s", sol);
summer_sum(sol);
}
char *summer_sum(char *solcs)
{
int i = 0;
size_t len;
typedef struct {
char *asg[40];
} nlist;
nlist *n1 = malloc(sizeof(*n1));
if (n1 == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
len = strlen(solcs); /* No need to compute len on each iteration */
for (i = 0; i <= 38; i++) { /* you are filling 39 and declared 40 */
n1->asg[i] = calloc(1, len);
/* Always check the result of (m/c/re)alloc */
if (n1->asg[i] == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
strcpy(n1->asg[i], solcs);
printf("\n %d value is : %s", i, n1->asg[i]);
/* Don't forget to free */
free(n1->asg[i]);
}
free(n1);
return NULL;
}
Before using n1->... You will have allocate memory to n1 as well using calloc()
There are two problems which involves dynamic memory allocation in your code:
n1 is not initialized, you should add a statement like n1 = malloc(sizeof(*n1)); before the for statement in summer_sum()
you did not allocate enough space for each asg[i], you should allocate spaces for these asg[i] by n1->asg[i] = malloc(strlen(**solcs) + 1);
You are using your pointer n1 uninitialized. Your program invokes undefined behavior. In such case you may get either expected or unexpected result.
Second, you are missing a closing brace } in function summer_sum.