I have a function that receives by a pointer the location where will be stored. This place can have different other similar structs.The function has to read a file. This file have stored a struct, which i need to read.
typedef struct user_manage_t{
short int user_id;
char permission;
long int other_id;
long int check;
}user_manage_t;
typedef struct holder_t{
user_manage_t *user_manage;
user_manage_t *user_manage_backup;
//(...)and a lot of stuff
}holder_t;
holder_t holder;
int db_read_from_file(user_manage_t *prt){
DEBUG_PRINT("READ_FROM file started");
FILE *fd_read;
char buffer[480];
int read, bytesRead=0;
int num;
const struct user_manage_t *header;
fd_read = fopen("/home/user/user_list","r+b");
if (fd_read == NULL)
{
printf("Error");
}
else
{
DEBUG_PRINT("Its open!!!");
}
do
{
read=fread(buffer, 2, 90, fd_read);
bytesRead=bytesRead+read;
DEBUG_PRINT("Number of bytes lidos read=%d",bytesRead);
}while(read!=0); //(bytesRead < 480);
header = (struct user_manage_t *) (buffer);
fclose(fd_read);
if ( NULL == ( prt = calloc( 10, sizeof(user_manage_t))))//aloca
{
DEBUG_PRINT("MAJOR_ERROR: couldnt allocate mem to users");
return -1;
}
else
{
memcpy( (struct user_manage_t *) &prt, &buffer, 90);
DEBUG_PRINT("Users copied to main list");
for ( short int i=0;i<4 ; i++ )
{
DEBUG_PRINT("i= %hd",i);
DEBUG_PRINT("User id: %d",holder.user_manage[i].user_id );
DEBUG_PRINT("Permission: %d",holder.user_manage[i].permission);
DEBUG_PRINT("other_ID:%ld",holder.user_manage[i].other_id);
DEBUG_PRINT("Check_value:%ld", holder.user_manage[i].check);
}
return 1;
}
}
main(){
db_read_from_file((struct user_manage_t *) &holer.user_manage);
db_read_from_file((struct user_manage_t *) &holder.user_manage_backup);
}
When I run the code I get SEGFAULT and valgrind tell me this,
Thread 2:
==2746== Invalid read of size 2
==2746== at 0x80523B4: db_read_from_file (code.c:3069)
==2746== by 0x20303333: ???
==2746== Address 0x0 is not stack'd, malloc'd or (recently) free'd
This is the line of "DEBUG_PRINT("User id: %d",holder.user_manage[i].user_id );" So obviously looks like I am not storing it in the right place.
Can u help me?
Priority Nr 1
After looking at your code a bit more, I suspect you're casting as much as you do, because you kept getting compiler warnings about "incompatible [pointer] types" and the like. Those warnings exist for a reason: there's an issue, a possible source for bugs there. Don't hush it up, don't ignore it: FIX IT!
Yes, sometimes those casts are required, and sometimes compilers complain about your code when you know what you're doing. In that case, you can add a cast, but don't think of those casts as compiler-gags: they are ways to tell the compiler that you know what you're doing. You've just gone cast-crazy to get the compiler to shut up. That's bad.
Next
In both your db_read_from_file calls from main, you are passing pointer to a null pointer to your function. That means you still have to allocate memory to actually go and store that data, or you have to redefine holder to something like:
struct
{
user_manage_t user_manage;//not pointers, actual structs
user_manage_t user_manage_backup;
} holder;
If you keep them as pointers, just allocate all members of holder in main:
holder.user_manage = malloc(sizeof *holder.user_manage);//and so on
//preferably, though:
if (NULL == (holder.user_manage_backup = malloc(sizeof *holder.user_manage_backup))
exit (EXIT_FAILURE);//error
The big one
As sth already mentioned:
memcpy( (struct user_manage_t *) &prt, &buffer, 90);
You are passing &prt, which reads: address of prt. This variable in itself is already a pointer, the memory address of a pointer is, again, a pointer. A pointer to a pointer (double indirection, avoid if possible...). Now as if that weren't enough: look at what you pass to your function:
db_read_from_file(&holder.user_manage);
Keep in mind that holder.user_manage already is a pointer, you are passing a pointer to a pointer! Thats double indirection. Then, you pass a pointer to this pointer to a pointer to memcpy!! Yes, you may have to read this last sentence again. But in short: you are passing a pointer, to a pointer, to a pointer to a struct, where that last bit (the pointer to a struct) could just be a null-pointer, too!
So what you have is this:
memcpy(void ***, char *, 90);//where the prt is void ***, and **prt could be NULL
Think about memcpy as a function that, basically does this:
void * memcpy( void *target, const void *src, size_t nr_of_bytes)
{
char *dest = target;
char *from = src;//use char, as it is guaranteed to be 1 byte in size
int i;
while(nr_of_bytes--)
*dest++ = *from++;//copy byte to destination, move pointer 1 byte
return dest;//return destination
}
Notice that the destination is being dereferenced (*dest++). If you pass a pointer to a pointer(&prt), and dereference it, you end up with a pointer, right? That's what you are writing to => *(&prt) == prt!
The cast, and the way you use it suggest you believe you're writing to whatever prt is pointing to, while in fact you are trying to write 90 bytes to whatever the pointer to prt is pointing to. And it's pointing to prt, which in turn points to a pointer. Only after this third inderiction, we find the struct... that's just crazy.
Anyway, the size of a pointer is 4 bytes on a 32 bit system, 8 on 64 bits. You are copying 90 bytes, so you probably end up in memory you shouldn't mess with.
Replace your code with this:
memcpy(*prt, buffer, sizeof *prt);//copy max the sizeof whatever prt is pointing to
And change the db_read_from_file function to this:
int db_read_from_file(user_manage_t **prt)//pointer to pointer!
And keep in mind that, whenever you want to change something of the struct that prt points to (2nd level), you have to dereference it, to get a regular pointer. For example, allocating memory:
if ( NULL == ( prt = calloc( 10, sizeof(user_manage_t))))//aloca
Has to become:
if ( NULL == ( *prt = calloc( 10, sizeof(user_manage_t))))//aloca
However, this is still wrong in many ways. What you actually need, is realloc, because prt might already be pointing at allocated memory:
*prt = realloc(*prt, 10*sizeof **prt);
if (*prt == NULL)
//ERROR
It's cleaner, and safer.
Also check if your function isn't being passed a null pointer, do away with needless casts (they're clutter), and always check the return value of functions!
Here's the final code, in case some one stumbles in a similar situaion:
typedef struct user_manage_t{
short int user_id;
char permission;
long int other_id;
long int check;
}user_manage_t;
typedef struct holder_t{
user_manage_t *user_manage;
user_manage_t *user_manage_backup;
pthread_mutex_t check_mutex;
pthread_mutex_t backup_mutex;
//(...)and a lot of stuff
}holder_t;
holder_t holder;
int db_read_from_file(user_manage_t **prt, pthread_mutex_t mtx){
DEBUG_PRINT("READ_FROM file started");
FILE *fd_read;
char buffer[480];
int read, bytesRead=0;
int num;
const struct user_manage_t *header;
fd_read = fopen("/home/user/user_list","r+b");
if (fd_read == NULL)
{
printf("Error");
}
else
{
DEBUG_PRINT("Its open!!!");
}
do
{
read=fread(buffer, 1, 480, fd_read);
bytesRead=bytesRead+read;
DEBUG_PRINT("Number of bytes lidos read=%d",read);
}while(read!=0); //(bytesRead < 480);
header = (struct user_manage_t *) (buffer);
fclose(fd_read);
if ( NULL != prt )
{
status = pthread_mutex_trylock (&mtx);
if (status != 0)//compor isto
{
DEBUG_PRINT("ERROR with lock");
return -1;
}
else
{
num = bytesRead / sizeof(user_manage_t);
DEBUG_PRINT("prt is not null and num=%d",num);
//should add an if to check if num >0
//if ( NULL == ( *prt = calloc( num, sizeof(user_manage_t))))//aloca
if ( NULL == ( *prt = malloc(bytesRead)))
{
DEBUG_PRINT("MAJOR_ERROR: couldnt allocate mem to users");
status = pthread_mutex_unlock(&mtx);
return -1;
}
else
{
//memcpy( *prt, header, sizeof(**prt));
memcpy( *prt, header, bytesRead);
DEBUG_PRINT("Users copied to main list");
status = pthread_mutex_unlock(&mtx);
for ( short int i=0;i<4 ; i++ )
{
DEBUG_PRINT("i= %hd",i);
DEBUG_PRINT("User id: %d",holder.user_manage[i].user_id );
DEBUG_PRINT("Permission: %d",holder.user_manage[i].permission);
DEBUG_PRINT("other_ID:%ld",holder.user_manage[i].other_id);
DEBUG_PRINT("Check_value:%ld", holder.user_manage[i].check);
}
return 1;
}
}
}
if ( NULL == prt )
{
DEBUG_PRINT("Pointer is null!");
return 0;
}
}
main(){
db_read_from_file(&holer.user_manage, holder.check_mutex);
db_read_from_file(&holder.user_manage_backup, holder.backup_mutex);
}
I am not sure if I am checking the null prt well, but the rest is working.
I made a small changes to be "perfect" is only missing thing is sending the filename as input of the function.It looks like the mutex is working with 100% sure.
Related
I'm fairly new to pointers, and void pointers is still black art to me.
In the following code I get a segfault when tmp->item = strdup(item);
I'm not sure how to fix.
int springmap_add(SpringMap *sm, char *key, void *item) {
SpringMap *tmp = sm;
.
.
.
while (tmp) {
if (!tmp->next) {
tmp->next = springmap_init();
tmp->next->key = strdup(key);
tmp->next->item = strdup(item); // Segfault here
return 1;
}
tmp = tmp->next;
}
return 0
}
int main(int argc, char* argv[]) {
char* key[ESTS] = {"alpha"};
void* ptr[ESTS] = {(void*)0xdeadbeef};
SpringMap* map = springmap_init();
for(int i = 0; i < TESTS; i++) {
int status = springmap_add(map, key[i], ptr[i]);
}
springmap_free(map);
return 0;
I'm not up to speed on void pointers.
The function name already tells: strdup composes of string duplicate, and it only is able to duplicate null-terminated C-strings (well, admittedly any data as long as it contains a null byte somewhere, though it would get cut off too early unless this null byte was the very last byte within the data).
void pointers in C have the unfortunate nature of implicitly converting to any other pointer type, happening in your code as well. However these pointers do not point to null-terminated C-strings, actually, they aren't even valid at all (most of most likely, at least)! Thus trying to read from them yields undefined behaviour.
So at first make sure that your void pointers point to valid memory. To use strdup they should point to C-strings, otherwise memcpy is the way to go, though you need to malloc storage space as target first. For both, you need the size of the object available, though. However you cannot get that back from the void pointer any more, thus you need yet another parameter.
You could write your own objdup function covering the duplication:
void* objdup(size_t size, void* object)
{
void* copy = malloc(size);
if(copy)
{
memcpy(copy, object, size);
}
return copy;
}
Still your pointers need to be valid! Some possible example might look like:
int main()
{
SomeDataType o1;
AnotherDataType o2;
AnotherDatatType* ptr = &o2; // create a valid pointer
// (could be done by malloc'ing memory, too)
void* c1 = objdup(sizeof(o1), &o1);
// ^ take the address of a REAL object!
if(c1)
{
void* c2 = objdup(sizeof(*o2), o2); // or via pointer to REAL object
if(c2)
{
// ...
free(c2);
}
free(c1);
}
return 0;
}
I am a newbie in C and I am trying to program a simple text editor, I have already written a 100 lines of stupid messy code, but it just worked. Until this SEGFAULT started showing up. I am going with the approach of switching terminal to canonical mode, and getting letter by letter from the user and do the necessary with each of 'em. The letters are added to a buffer, which is realloced extra 512 byte when the buffer is half filled, which I know is a stupid thing to do. But the cause of the SEGFAULT cant be determined. Help would be appreciated. Here's my code:
char* t_buf
int t_buf_len = 0;
int cur_buf_sz = 0;
void mem_mgr(char *buffer, unsigned long bytes){ //Function to allocate requested memory
if(buffer == NULL){
if((buffer = malloc(sizeof(char) * bytes)) == NULL){
printf("ERROR:Cannot get memory resources(ABORT)\n\r");
exit(1);
}
}
else{
realloc(buffer, bytes);
}
}
void getCharacter(){
if(t_buf_len >= (cur_buf_sz/2))
mem_mgr(t_buf, cur_buf_sz+=512);
strcpy(t_buf, "Yay! It works!");
printf("%s %d", t_buf, cur_buf_sz);
}
There are things you need to understand first,
The buffer pointer is a local variable inside the mem_mgr() function, it points to the same memory t_buf points initially, but once you modify it, it's no longer related to t_buf in any way.
So, when you return from mem_mgr() you lose the reference to the allocated memory and.
To fix this, you can pass a poitner to the pointer, and alter the actual pointer by dereferencing it.
The realloc() function, behaves exactly like malloc() if the first argument is NULL, if you read the documentation you would know that.
Memory allocation functions MUST be checked to ensure they returned a valid legal pointer, that's why you need a temporary poitner to store the return value of realloc(), because if it returns NULL, meaning that there was no memory to fulfill the request, you would lose reference to the original block of memory and you can't free it anymore.
You need to pass a pointer to your pointer to mem_mgr(), like this
int
mem_mgr(char **buffer, unsigned long bytes)
{
void *tmp = realloc(*buffer, bytes);
if (tmp != NULL) {
*buffer = tmp;
return 0;
}
return -1;
}
And then, to allocate memory
void
getCharacter()
{
if (t_buf_len >= (cur_buf_sz / 2)) {
if (mem_mgr(&t_buf, cur_buf_sz += 512) != -1) {
strcpy(t_buf, "Yay! It works!");
printf("%s %d", t_buf, cur_buf_sz);
}
}
}
The call to
mem_mgr(t_buf, cur_buf_sz+=512);
cannot change the actual parameter t_buf. You will either have to return the buffer from mem_mgr
t_buf = mem_mgr(t_buf, cur_buf_sz+=512);
or pass a pointer to t_buf
mem_mgr(&t_buf, cur_buf_sz+=512);
Furthermore, a call to realloc may change the address of the memory buffer, so you will have to use
char *tmpbuf = realloc(buffer, bytes);
if (!tmpbuf)
// Error handling
else
buffer = tmpbuf;
realloc(NULL, bytes); will behave like a malloc, so you don't need a separate branch here. This makes in total:
char *mem_mgr(char *buffer, unsigned long bytes){ //Function to allocate requested memory
char *tmpbuf = realloc(buffer, bytes);
if (!tmpbuf) {
// Error handling
}
return tmpbuf;
}
which somehow questions the reason of existence of the function mem_mgr.
I've done some research and couldn't find any answer to my problem.
I'm having problems with freeing my struct.
This is how i create my struct:
struct Structure * newStructure(int N)
{
struct Structure * structure;
int i;
structure = (struct Structure * ) malloc(N * sizeof(struct Structure));
for (i = 0; i < N; i++)
{
structure[i].i_Number = (int * ) malloc(sizeof(int));
structure[i].c_Char = (char * ) malloc(sizeof(char));
structure[i].c_Char[0] = '\0';
structure[i].d_Float = (double * ) malloc(sizeof(double));
}
return structure;
}
Everything works to this point. Later I fill every variable with random values so that they are not empty.
I call my freeMemory function like this freeMemory(structure, amountOfStructures);
And here is freeMemory function itself:
void freeMemory (struct Structure* structure, int N)
{
int i;
for( i=0 ; i<N ; i++ )
{
if (structure[i].i_Number!=NULL) free(structure[i].i_Number);
if (structure[i].c_Char!=NULL) free(structure[i].c_Char);
if (structure[i].d_Float!=NULL) free(structure[i].d_Float);
}
free(structure);
}
The free(structure) part works fine. But there are problems with the for loop and I have no idea what I'm doing wrong here.
#EDIT
I'm adding my struct declaration:
struct Structure{
int *i_Number;
char *c_Char;
double *d_Float;
};
#EDIT2
That's the function that initializes struct:
struct Structure* randomizing (int N)
{
struct Structure* structure = newStructure(N); int i;
srand(time(NULL));
for (i = 0; i < N; i++)
{
int _i; char _c; double _d;
_i = rand()%1000000;
_c = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" [rand () % 26];
_d = 0;
setStructureNumber(structure, i,(int*) _i);
setStructureChar(structure, i, (char*) _c);
setStructureDouble(structure, i, &_d);
// I'VE COMMENTED OUT THE MUTATORS ABOVE AND THE ERROR DOES NOT SHOW ANYMORE, SO THERES SOMETHING WRONG WITH THEM
}
return structure;
}
And im calling it like this:
struct Structure* structure;
structure = randomizing(amountOfStructures);
The mutators used:
// Mutators
void setStructureNumber (struct Structure* structure, int p, int* num)
{
if (structure[p].i_Number != NULL) free(structure[p].i_Number);
structure[p].i_Number = (int*) malloc (sizeof(int));
structure[p].i_Number = num;
}
void setStructureChar (struct Structure* structure, int p, char* str)
{
if (structure[p].c_Char != NULL) free(structure[p].c_Char);
structure[p].c_Char = (char*) malloc (sizeof(char));
structure[p].c_Char = str;
}
void setStructureDouble (struct Structure* structure, int p, double* dou)
{
if (structure[p].d_Float != NULL) free(structure[p].d_Float);
structure[p].d_Float = (double*) malloc (sizeof(double));
structure[p].d_Float = dou;
}
The most likely reason is that somewhere in your code you go out of bounds of the memory you allocated and thus destroy the integrity of the heap. A frequently encountered practical manifestation of such undefined behavior is a failure at free, when the library detects the problem with the heap.
Inside you allocation cycle you allocate just one object of each respective type for each field of your struct object. For example, you allocate only one character for c_Char field and initialize it with \0. This might suggest that c_Char is intended to hold a string (is it?). If so, then the memory you allocated is sufficient for an empty string only. If you do not reallocate that memory later, any attempts to place a longer string into that memory will break the integrity of the heap and trigger undefined behavior.
The same applies to other fields as well. However, without extra explanations from you it is not possible to say whether it is right or wrong. At least, you have to provide the definition of struct Structure. And you have to explain your intent. Why are you dynamically allocating single-object memory for struct fields instead of just making these objects immediate members of the struct?
The additional code you posted is completely and utterly broken.
Firstly you are calling your mutators as
setStructureNumber(structure, i,(int*) _i);
setStructureChar(structure, i, (char*) _c);
setStructureDouble(structure, i, &_d);
This does not make any sense. Why are you trying to convert integer value _i to pointer type??? If you want to obtain a pointer to _i, it is done as &_i. You already do it correctly in the very last call, where you pass &_d. Why are the first two calls different from the last one? What was your logic behind this?
Secondly, inside your mutator functions
void setStructureNumber (struct Structure* structure, int p, int* num)
{
if (structure[p].i_Number != NULL) free(structure[p].i_Number);
structure[p].i_Number = (int*) malloc (sizeof(int));
structure[p].i_Number = num;
}
you are freeing old memory and allocating new memory. Why? Why don't just reuse the old memory to store the new value? (BTW, there's no need to check the pointer for null before calling free, because free will check it internally anyway.)
Thirdly, after allocating the new memory you immediately leak it by overriding the pointer value returned by malloc with the pointer value passed from the outside
structure[p].i_Number = num;
Again, this does not make any sense. This is actually what causes the crash on free - the pointers you pass from the outside are either meaningless random values (like your (int *) _i or (char *) _c)) or point to a local variable (like your &_d).
There's no way to "correct" your code without knowing what it is you are trying to do in the first place. There are just too many completely unnecessary memory allocations and reallocations and other illogical things. I would simply rewrite the mutator functions as
void setStructureNumber (struct Structure* structure, int p, int num)
{
*structure[p].i_Number = num;
}
Note - no memory reallocations and the argument is passed by value.
The functions would be called as
setStructureNumber(structure, i, _i);
setStructureChar(structure, i, _c);
setStructureDouble(structure, i, _d);
But again, this is so vastly different from what you have that I don't know whether this is what you need.
Technically, there is nothing wrong with what you are doing (except the missing error checks on allocations, unnecessary casts of malloc results, and unnecessary NULL checking before calling free).
This should work fine, assuming that you pass the correct value of N, and that you do not free things more than once:
struct Structure * newStructure(int N) {
struct Structure * structure = malloc(N * sizeof(struct Structure));
for (int i = 0; i < N; i++) {
structure[i].i_Number = malloc(sizeof(int));
structure[i].c_Char = malloc(sizeof(char));
structure[i].c_Char[0] = '\0';
structure[i].d_Float = malloc(sizeof(double));
}
return structure;
}
void freeMemory (struct Structure* structure, int N)
{
for(int i=0 ; i<N ; i++ )
{
free(structure[i].i_Number);
free(structure[i].c_Char);
free(structure[i].d_Float);
}
free(structure);
}
You can use a memory diagnostic tool such as valgrind to ensure that you do not freeing things more than once.
In your mutators you leak memory and then point to local variables (comments mine)
void setStructureChar (struct Structure* structure, int p, char* str)
{
if (structure[p].c_Char != NULL) free(structure[p].c_Char);
// allocates new memory and points c_Char at it.
structure[p].c_Char = (char*) malloc (sizeof(char));
// makes c_Char point to where `str` is pointing; now the allocated memory is leaked
structure[p].c_Char = str;
}
When you later do free on structure[p].c_Char, it causes undefined behaviour because you called this function with a pointer to a local variable. You probably have undefined behaviour elsewhere too if you try to access c_Char anywhere before freeing it.
The other mutators have the same problem.
To "fix" this change structure[p].c_Char = str; to *structure[p].c_Char = *str;.
You also have blunders here:
setStructureNumber(structure, i,(int*) _i);
setStructureChar(structure, i, (char*) _c);
You meant &_i and &_c respectively. I would advise to remove all casts from your code. At best they are redundant; at worst (e.g. in these two lines) they hide an error which the compiler would diagnose.
Also remove all the NULL checks before free, they are redundant and make your code hard to read. Instead, do the NULL checks after calling malloc, and abort the program if malloc returned NULL.
However this whole setup seems like a ghastly design. You could pass the things by value to the mutators. And you could change your struct to not contain pointers, and therefore not need all this extra allocation.
In one function I used malloc :
void name1(struct stos* s)
{
s = malloc (4 * sizeof (int));
}
And everything is ok. But later I used realloc
void name2(struct stos* s)
{
s->size = 2*(s->size);
s = realloc (s, (s->size + 1) * sizeof (int));
}
and I get invalid free/delete/realloc in valgrind and realloc returns NULL.
Declaration of Structure and rest of program is:
struct stos
{
int top;
int size;
int stk[];
};
void name1(struct stos* s);
void name2(struct stos* s);
int main()
{
struct stos stosik;
struct stos* s;
s = &stosik;
name1(s);
//some operations on the array and int top here
name2(s);
}
What did I do wrong here? I looked for what might have gone wrong for quite long, read quite a few articles about pointers, malloc/realloc etc. but with no result. I would be really grateful, if someone could help me.
The problem is slightly subtle and caused by a combination of two things. Let's start here:
struct stos stosik;
struct stos* s;
s = &stosik;
name1(s);
First, you make s point to an a valid chunk of memory that is allocated on the stack (stosik) and then you call name1 passing into s. Let's look at what name1 looks like:
void name1(struct stos* s)
{
s = malloc (4 * sizeof (int));
}
Hmm, we can see that name1 takes in a pointer to a struct stos called s; inside that function, we are allocating some memory and making s point to it. This is a problem.
First of all, note that s already points to a valid chunk of memory. So using a malloc here is suspicious. It will cause a subtle bug that will actually hide the real bug in your program, which is bad. So, let's remove stosik completely:
int main()
{
struct stos* s = NULL;
name1(s);
if(s == NULL)
return -1;
Now, if you run this program, you will see that after you call name1 the variable s still points to NULL. What's happening here?
Well, we are changing the function's LOCAL copy of s (i.e. the s that exists only inside name1)... but the s in main isn't changed! Remember, that we are passing a pointer into name1 but we are passing it by value.
To do what you seem to be trying to do you can do you would have to either pass a pointer to s into name1 (that is, to pass a double pointer) or you should return the result of the malloc from name1 as a return value. Let's look at each of these options:
Passing s in via a double pointer
void name1(struct stos **s)
{
/* sanity check */
if(s == NULL)
return;
/* now, allocate enough space for four integers and make
* whatever s points to, point to that newly allocated
* space.
*/
*s = malloc(4 * sizeof(int));
}
And calling it from main requires us to use the "address-of" operator:
struct stos *s = NULL;
/* we need to pass a pointer to s into name1, so get one. */
name1(&s);
/* malloc can fail; check the result! */
if(s == NULL)
return -1;
Returning a pointer to the allocated memory from name1
struct stos *name1()
{
return malloc(4 * sizeof(int));
}
Calling this from main is slightly easier:
struct stos *s = name1();
/* malloc can fail; check the result! */
if(s == NULL)
return -1;
Changing your code to what I show you here will fix this issue (but there may be others) but let me touch briefly upon something else:
The other bug
The crash you encounterd crops up partially because of the problem we just covered; another issue is that inside name2 you are calling realloc. The pointer you pass into realloc however, is not a pointer that you got back from malloc or realloc, which is what realloc expects. It points to stosik instead. So that code causes undefined behavior and after that anything can happen.
If you're lucky (it seems you were), it will just crash right then and there and if you're not... well, who knows what will happen?
if you want to dynamically allocate s in name1 you need it to be declared as name1(struct stos** s) and pass pointer to the pointer where the allocated memory should appear.
Your main allocates stosik staticaly, meaning you don't need to do any further dynamic allocation. Then when you try doing name1(statically allocated mem) it does … um, something. I don't know what, but certainly not what you expect.
I have implemented a hashmap.
struct hashmap_elmnts
{ char *key;
int in_use;
void *data; //contains the address of the malloc of struct ussd defined below
};
struct hashmap_map
{
int table_sizel;
int size;
struct hashmap_elmnts *element ;
};
Now, I have another structure USSD
typedef struct ussd { char menu;
int8_t did;
int8_t invokeid;
char *language;
char *msisdn;
char *ussd_string;
} USSD;
Now, while inserting in the HASHMAP,
USSD *init = (USSD*)malloc(sizeof(USSD));
init->msisdn = (char*)malloc(sizeof(char));
init->language = (char*)malloc(sizeof(char));
init->ussd_string = (char*)malloc(sizeof(char));
msisdn = language = ussd_string = NULL;
Then, I assign some values and then insert in the hashmap
However, while getting the information back, i face some issue:
IN FILE GET.c
I call a function
USSD *pointer = NULL;
res = hashget(key, pointer);
if (pointer == NULL)
printf ("pointer fail\n");
else
printf ("pointer pass\n");
IN FILE HASHGET.c
int hashget(int key, USSD_STRUCT *arg)
{
/** declaring a hashmap_map pointer **/
struct hashmap_map *m;
now, after various calculation -> i find a value of 'curr'
arg = (m->element[curr].data);
if (arg == NULL)
printf("fail\n");
else
printf ("pass\n"):
return 1;
}
THE OUTPUT IS AS FOLLOWS:
pass
pointer fail
How is this possible, when arg != NULL but still the pointer is NULL. As i expected any assignment at arg would be reflected in pointer also.
Can anybody let me what could have gone wrong. I'm unable to share the entire code snippets as the code is huge..
In your first block of code you are saying you if assign null to pointer not if pointer equals null.
if (pointer = NULL)
This is your problem. If your compiler isn't warning you about this, either turn your warnings up, or find a better compiler. What you want is what you have in your second if block:
if (pointer == NULL)
The reason it isn't working with the one = is because you are assigning NULL to pointer within the if statement. The result of that expression is NULL, hence the if block doesn't execute, but the else block does.
Alternatively, some people find it easier to read by omitting the comparison to NULL altogether:
if (pointer)
{
// pointer is not NULL
}
else
{
// pointer is NULL
}
Use this way (Make following changes at respective places)
...
res = hashget(key, &pointer);
if (pointer == NULL)
printf ("pointer fail\n");
else
printf ("pointer pass\n");
...
...
int hashget(int key, USSD_STRUCT *arg)
...
...
*arg = data;
if (*arg == NULL)
printf("fail\n");
else
printf ("pass\n"):
return 1;
}
...
Reason:
In your program you are passing pointer as pass by value, In my method I am passing as pass by pointer or basically passing the address of pointer because its value needs to be modified in calling function.
EDIT: (After your modification in the question)
USSD init = (USSD)malloc(sizeof(USSD));
This is wrong. init should be a pointer.
Use USSD *init = (USSD*)malloc(sizeof(USSD));.
And after you allocated memory to init->msisdn, init->language, init->ussd_string, why are you setting them to NULL, that too just by referencing the inner variables of struct like this: msisdn = language = ussd_string = NULL.
And even if you correct all these mistakes, my answer is OK, since you cannot modify value of pointer by making a call like this: res = hashget(key, pointer);, using this you can only modify *pointer i.e. value pointed to by the pointer.