I'm currently working on modifying a dump program, but I can't figure out how to properly navigate with a void pointer. Below is the function that I'm working in, and the instruction that I'm trying to execute. I've tried casting mem to a struct, but I'm not sure of the sytnax and I keep getting an error. For the code below, the specific error I'm getting is:
47 | mem = mem->tcbtio
===========> .........a..............................................
*=ERROR===========> a - CCN3122 Expecting pointer to struct or union.
Here is my function:
void hexdump(void *mem, unsigned int len)
{
mem = mem->tcbtio;
...
}
Here are my struct defintions:
struct psa {
char psastuff[540];
struct tcb *psatold;
char filler[4];
struct ascb *psaaold;
};
struct tcb {
struct prb *tcbrb;
char tcbstuff[8];
struct tiot *tcbtio;
};
struct tiot {
char tiocnjob[8];
char tiocpstn[8];
char tiocjstn[8];
};
I need to keep it as a void pointer, as I need to cast it to char and int later on in the function.
It seems as you are expecting to find a tcb struct, starting at the address pointed by mem, but the aim of the code is obscure and the question not clear.
If this is really the case, you can try this:
mem = ((struct tcb *)mem)->tcbtio;
You cannot dereference a void pointer. You can think it this way if you have a void pointer, how will compiler know what type of address it is holding. And by doing mem = mem->tcbtio how much offset it has to make.
Modify your function as:
void hexdump(void *mem, unsigned int len)
{
struct tcbtio *mem2;
mem2 = ((struct tcb*) mem) -> tcbtio;
...
// Use mem2 later
}
Related
I have a struct initialized on a stack, and i want to write data in memory right after the struct and make a pointer inside a struct point to that data.
I know it is achievable on the stack/heap with uninitialized structure using malloc(sizeof(struct) + additional size) or alloca(). but can i perform initialization of a data after the struct is already initialized on the stack? and can i perform this initialization inside a initializator function?
Simple example:
struct TEST {
wchar_t* itest;
};
void init_struct(struct TEST* test) {
// point to the end of the struct
char* walk_ptr = (char*)test + sizeof(test);
test->itest = (wchar_t*)walk_ptr;
// initialize data after the struct
...
}
int main(void) {
struct TEST test;
init_struct(&test);
return 0;
}
You could do this by embedding the structure inside another structure to reserve memory for the extra data:
int main(void)
{
struct { struct TEST test; wchar_t data[NumberOfElements]; } S;
init_struct(&S.test);
…
}
However, the code in init_struct adds an incorrect size, sizeof(test), to the pointer. You likely wanted to add sizeof (struct Test), or, equivalently, sizeof *test, since you want to get past the struct TEST that test points to, not past a struct TEST * that test is.
However, even adding the correct size of the structure would not guarantee strictly conforming C code, since C implementations may insert padding between structure members. Properly we would add the offset of the data member. To do that, we nwould eed to give the structure a tag and then either make the structure definition visible to init_struct or pass the offset to init_struct. However, it is easier just to pass the address of the extra data:
void init_struct(struct TEST *test, wchar_t *data)
{
test->itest = data;
}
int main(void)
{
struct { struct TEST test; wchar_t data[NumberOfElements]; } S;
init_struct(&S.test, S.data);
…
}
Of course, a pointer can point anywhere, and there is no apparent reason the data should be immediate after the structure, so we can disconnect them:
int main(void)
{
struct TEST test;
wchar_t data[NumberOfElements];
init_struct(&test, data);
…
}
I have a C code, somewhat similar to this:
struct st
{
int *var;
}
void fun(st *const ptr)
{
// considering memory for struct is already initialized properly.
ptr->var = NULL; // NO_ERROR
ptr = NULL; // ERROR, since its a const pointer.
}
void main()
{
//considering memory for struct is initialized properly
fun(ptr);
}
I dont want to declare int *var as const in the structure definition, so as not to mess with the huge code base. Not looking to make any change in the structure definition
Is there any way in C, to get an error for the NO_ERROR line
ptr->var = NULL; // NO_ERROR ?
Just declare the parameter with const, so the ptr is a pointer to a const object:
void fun(const struct st* ptr)
Your declaration makes ptr to be constant, but not the object to which it points. Also don't miss struct keyword
void fun(struct st *const ptr);
Instead you should use
void fun(const struct st *ptr);
Such declaration allows to change pointer but not the object to which it points.
Keep this in mind:
With type* const ptr, you cannot change the pointer but you can change the pointed data
With const type* ptr, you can change the pointer but you cannot change the pointed data
So all you need is to replace struct st* const ptr with const struct st* ptr.
Superb! Thank you so much guys!
I did this -
void fun(const struct st *const ptr);
and I was able to get an error while changing both ptr and ptr->var .. Just what I needed..
Is there anything wrong with this?
According to the compiler there is an error in this line
void memory_allocation(struct a *s1,struct b *s2,struct c *s3,int size)
main looks like
main()
{
struct mystack
{
int head;
void **stack;
void **stackcopy;
int stack_size;
} *ptr ;
struct professor
{
char flag;
char surname[50];
char coursbhe[50];
} *prof;
struct student
{
char flag;
char surname[50];
int semester;
} *stud;
(*ptr).stack_size=getstacksize();
memory_allocation(&ptr,&prof,&stud,(*ptr).stack_size);
}
Your types are local to the function (main()) in which they are defined. That means you cannot reliably pass variables of those types to any other function. You should define the types outside of main() so that other functions can use the same types. There is a concept of type equivalence, but there's also a concept called DRY — Don't Repeat Yourself. The only way another function could use those types is by writing them out again, repeating yourself. Don't!
Your types need to be available outside the function. You don't have to define any global variables when you define the types. For example, you could use:
struct mystack
{
int head;
void **stack;
void **stackcopy;
int stack_size;
};
struct professor
{
char flag;
char surname[50];
char coursbhe[50];
};
struct student
{
char flag;
char surname[50];
int semester;
};
extern int getstacksize(void);
extern void memory_allocation(struct stack **s1, struct professor **s2,
struct student **s3, int size);
extern void memory_release(struct stack *stack, struct professor *prof,
struct student *stud);
int main(void)
{
struct mystack *ptr = 0;
struct professor *prof = 0;
struct student *stud = 0;
int stack_size = getstacksize();
memory_allocation(&ptr, &prof, &stud, stack_size);
memory_release(ptr, prof, stud);
return 0;
}
Note that the memory allocation function cannot do anything useful unless:
It knows about the types of the structures it is to allocate.
It is passed pointers to the pointers so it can modify the actual pointers in the main().
The memory release function doesn't need pointer to pointer syntax, though it could be used and if it was used, the memory release function should set the pointed at pointers to NULL when the memory is released to minimize the risk of abusing already freed memory.
The additional variable stack_size is needed because ptr doesn't point to anything when getstacksize() is called, so referencing (*ptr).stack_size will probably crash and definitely not work correctly. Alternatively, you could change the definition of the variable to stack mystack stack; and then use stack.stack_size = getstacksize(); and pass stack.stack_size to the allocation function, but then you don't need the memory allocator to allocate the stack as a whole any more. Separation of duty suggests that there will be a separate function to allocate the stack internals.
All the material from the first struct mystack line down to but not including int main(void) is eligible to be put into a header so that the implementation of the functions can see the same type and function definitions as the main() program can see.
Here is the solution....
use your prototype of function as below
void memory_allocation(struct mystack *s1 , struct professor *s2 , struct student *s3 , int d)
because you are calling with defined struct not other and call should be like
memory_allocation(ptr,prof,stud,(*ptr).stack_size);
remove "&" sign or remove *s1 to s1(have to pass address ,not address of address)
please change both things, it will work,my side its working..
I want my struct to carry a string. I defined it like so:
typedef struct myStruct {
char* stringy
} myStruct
and a function
free(char *stringy){
//structObj is a struct object
structObj->stringy = stringy
}
Is this correct? I have a feeling that since it's a local variable, stringy will be lost, and the pointer will point to garbage.
Sorry, new with C.
It would be garbage if you were somehow using char** stringy, but structObj->stringy = stringy means "you know the thing that stringy points to? Now structObj->stringy points to that". Of course, it is still possible to unset the value which the pointer is pointing to, and at that point dereferencing will yield garbage.
Here's an example to make it clearer:
#include<stdio.h>
typedef struct mStruct {
char* stringy;
} myStruct;
myStruct * structObj;
void doSomething(char* stringy)
{
structObj->stringy = stringy;
}
int main(int argc, char* argv)
{
char* a = "abc\n";
structObj = malloc(sizeof(myStruct));
doSomething(a);
a = "qxr\n";
printf(structObj->stringy);
}// prints "abc\n"
If stringy is defined in callers of free function, as long as they keep the actual string in its place (where stringy points), no problem.
There is not any local variable declaration in your code.
You have to declare:
typedef struct myStruct {
char* stringy
} myStruct;
free(char *stringy){
myStruct *structObj;
structObj->stringy = stringy;
}
Pay attention to the semicolon that I've added to the end of the typedef declaration.
This was not not in your code.
The object structObj is a struct whose type is myStruct.
Now, your parameter stringy comes from another site, it is not lost.
But the struct structObj will have duration only inside your "free" function.
EDIT
I have fixed an error: the right declaration has to be "pointer to structObj", which is done in this way:
myStruct *structObj;
Observe that now myStruct is a non-initialized pointer, so the following assignment is legal:
structObj->stringy = stringy;
but will not work.
However I think this goes beyond the scope of the original question...
myStruct is type which you defined for your struct myStruct .that to you need to create an object before using.
you need to do like this:
typedef struct myStruct {
char *stringy;
} myStruct_t; //user defined data type
myStruct_t *obj;
// you need to allocate memory dynamically.
obj= (myStruct_t *) malloc(sizeof(myStruct_t));
usage:
scanf("%s",obj->stringy);
printf("%s",obj->stringy);
in function:
my_free(char *str) //str is local string
{
obj->stringy=str;
}
your can also try this code :
typedef struct myStruct {
char stringy[20]; //char *stringy
} myStruct_t; //user defined data type
myStruct_t obj; //object creation
usage:
scanf("%s",obj.stringy);
printf("%s",obj.stringy);
in function:
my_free(char *str) //str is local string
{
strcpy(obj.stringy,str);
}
You're correct that as soon as what it points to goes out of scope, it will point to garbage: this is a dangling pointer. You'll need to allocate some memory and perform a copy to fix this:
add_string(my_struct* s, const char* c)
{
size_t len = strlen(c);
s->file = malloc(len + 1);
strcpy(s->file, c);
}
Don't forget that you'll need to free it when you're done:
void destroy_struct(my_struct* s)
{
free(s->file);
free(s);
}
I declare a new struct with the name of "Struct"
I have a generic function that takes in an argument "void *data".
void Foo(void *data)
I pass an instance of "Struct" into the generic function.
Struct s;
Foo(&s);
I want to access one of the properties of the struct in the function.
void Foo(void *data) {
char *word = (char*) data.word;
}
It's not allowed because it doesn't recognize data as a valid struct.
I even try to declare the data as the struct type first, and I get an error.
void Foo(void *data) {
Struct s = (Struct) data;
char *word = s.word;
}
I get "conversion to non-scalar type requested".
First of all, you should turn on your compiler's warning flags (all of them). Then you should pass a pointer to your Struct and use something other than struct as a variable name:
Struct s;
Foo(&s);
Then, in Foo:
void Foo(void *data) {
Struct *s = data;
char *word = s->word;
}
You can't convert non-pointer types to and from void* like you're trying to, converting pointer types to and from void* is, on the other hand, valid.
You need to pass a pointer to you struct and get a pointer to the struct inside the function:
Struct struct;
Foo(&struct);
void Foo(void *data) {
Struct* struct = (Struct*) data;
char *word = struct->word;
}
You have to use -> operator when requesting structure member via pointer.
This should work: char *word = (char*) data->word;
You also have to pass the address of the structure to the function. Like this: Foo(&struct);.
Firstly you need to call the function correctly:
Struct s;
Foo(&s);
Notice you're now passing a pointer to the structure.
Now, the function has to know that you're using a Struct (as opposed to something else) - perhaps because of another parameter, or a global variable, or some other reason. Then inside the function you can do:
void Foo(void *data) {
Struct *structpointer = p; /* Note - no need for a cast here */
/* (determine whether data does refer to a pointer then...) */
char *word = structpointer->word;
/* ... then use 'word'... */
}
Data is pointer, so whatever you cast it to must also be a pointer. If you said Struct* myStruct = (Struct*) data, all would be well with the world.
You are mixing pointers and data.
Struct struct defines a data object
void *data expects data to be a pointer.
Call Foo with a pointer to a Struct, and make other necessary changes
Struct struct;
Foo((void*)&struct);
void Foo(void *data) {
Struct *struct = (Struct*)data;
char *word = struct->word;
}
or the more compact form:
Struct struct;
Foo((void*)&struct);
void Foo(void *data) {
char *word = ((Struct*)data)->word;
}