Doing a direct struct read in C from preallocated memory failed - c

I'm assuming its a pointer issue again, but what I'm trying to do here is have a function search memory to see if an IP address exists, and if it doesn't then a random memory space is reserved for the IP address and zero is returned. the function takes an IP address as a string as the 1st parameter and the second parameter points to the struct. When the main() function is executed, result should equal 0 and result2 should equal 1, but instead, I get crashes, and I think it has to do with the way I'm assigning pointers?
In this fragment...
ip=(iprec*)p;
I'm trying to set the iprec structure passed into the function (and previously allocated by malloc), but I'm not sure where to add or remove stars from that statement.
Here is the rest of the code.
char *shma;
typedef struct{
unsigned char u;
unsigned char a[4];
unsigned int otherdata;
} iprec;
static int loadip(char* remoteip,iprec *ip){
char *p=shma;
int v=0;
char *ep;
unsigned char a[4];
sscanf(remoteip,"%d.%d.%d.%d",a[0],a[1],a[2],a[3]);
int i,n;int sz=5000;
int szr=sizeof(iprec);
for (i=3;i<sz;i+=szr){
ip=(iprec*)p;
if (ip->u=='Y'){
for (n=0;n<=4;n++){
if (a[n]!=ip->a[n]){break;}
}
if (n >= 3){v=1;break;}
}else{
ep=p;
}
p+=szr;
}
if (v==0){
ip=(iprec*)ep;
for (n=0;n<=3;n++){
ip->a[n]=a[n];
}
}
return v;
}
int main(){
char *shma=(char*)malloc(5000); //alloc 5000 bytes for example.
iprec *x=(iprec*)malloc(sizeof(iprec));
int result=loadip("127.0.0.1",x);
int result2=loadip("127.0.0.1",x);
}

Replace
sscanf(remoteip,"%d.%d.%d.%d",a[0],a[1],a[2],a[3]);
With
sscanf(remoteip,"%d.%d.%d.%d",&a[0],&a[1],&a[2],&a[3]);
sccanf needs pointer type arguments.
shma should be global.

I haven't done a full analysis of your code, but here is a source of your crash. At the bottom is a resolution
Analysis
At the top of your snippet, you have
char *shma;
This is a file-scope (global) object called shma that has static duration storage. It gets initialized to 0 prior to main() executing.
Then, in main, you have:
int main(){
char *shma=(char*)malloc(5000); //alloc 5000 bytes for example.
Here you declare a new object called shma. It has block scope (exists only within the context of main), with automatic storage. You assign to it a pointer from malloc(). Then you call loadip.
loadip has
char *p=shma;
Which declares a new object called p with block scope (exists in loadip) with automatic storage. You set it to shma. NOTE this is assigning the global shma, not the one in main, because the one in main only exists within main, and loadip is outside of main. The global shma was 0, so now p is also 0 (at least for your first loop).
Then, you do:
ip=(iprec*)p;
so, since p was 0, now ip is 0. In the next line:
if (ip->u=='Y'){
you are dereferencing ip to obtain member u. On most systems, this dereference will result in a segmentation fault (or similar memory access violation), because you have essentially dereferenced NULL (the 0 address).
Fix for this issue
Change
int main(){
char *shma=(char*)malloc(5000); //alloc 5000 bytes for example.
into
int main(){
shma=(char*)malloc(5000); //alloc 5000 bytes for example.
This will result in main assigning to the global shma instead of creating a new local one.

Its a while since I've done C, but a few thoughts :
char *p=shma;
but shma has not yet been initialised - and consequently the "ip=(iprec*)p;" means ip will not be a valid value.
unsigned char a[4];
sscanf(remoteip,"%d.%d.%d.%d",a[0],a[1],a[2],a[3]);
you need the address of the receiving variables (ie. &a[0], &a[1], ...).
Also, since '%d' will write 4 byte integers (the scanf doesn't know it's a char array), better to have "int a[4]"
ip=(iprec*)p;
But ip is an input parameter - so here you're overwriting (ie. throwing away) whatever value the user supplied in the second argument.
if (v==0){
ip=(iprec*)ep;
Even if v=0, it is still possible that ep has not been initialised (eg.if all ip->u == 'Y' but the a-arrays differ on the first or second values)

Related

Passing struct pointer to two functions and then calling malloc

I have a struct in my main function. I pass that pointer to another function which does some stuff and if conditions are met, it passes it to another function to get filled out. When returning to the main function the t struct contains none of the data mydata that was copied into it.
typedef struct _t {
int one;
int two;
int three;
int four;
} T;
void second(T *t) {
t = malloc(20);
memcpy(t, mydata, 20);
}
void first(T *t) {
second(t);
}
int main() {
T t;
first(t);
}
Do I need to be working with double pointers here? If the address of t was 0x1000 and I passed it to first() then wouldn't referencing t just be 0x1000? And same as if I pass the pointer to second()?
In this answer, I assume that, for reasons not shown, you do in fact need to make a dynamic memory allocation. If that is not the case, the only changes that need to be made are replacing first(t); with first(&t);, and removing t = malloc(20);.
The first problem to fix is that t in main should have the type T *, not T. You are making a dynamic memory allocation, and seem to want to store that pointer in t, so you would need: T *t;.
The second problem is that you want to manipulate the value of t in main, but are passing it by value to first. Instead, you need to pass a pointer to t into first: first(&t);.
Fixing both of these, you now pass a pointer to a pointer to T (the type of &t) into first and second, so you need to change their signatures to be, respectively, void first(T **t) and void second(T **t).
Applying both changes, as well as making some small style tweaks, we get:
typedef struct T {
int one;
int two;
int three;
int four;
} T;
void second(T **t_ptr) {
*t_ptr = malloc(20);
memcpy(*t_ptr, mydata, 20);
}
void first(T **t_ptr) {
second(t_ptr);
}
int main() {
T *t;
first(&t);
}
Another thing that's missing, and needs to be added, is checking for the success of malloc, but I haven't added that to the above code.
Also, what you've shown in the question shouldn't compile; you're passing a struct to a function that accepts a pointer.
Your problems are common to new C developers. And actually you have two of them.
The first problem is that you pass your structure by value.
The first function is declared to receive a pointer to T but you pass t and not &t (which is the address of t - and this is what you want when a function accepts a pointer).
However there is still another problem so that even if you change your code as suggested above it will still not work correctly. second allocates memory using malloc. The function receives T as a pointer T *t. You assign the output of malloc to t in effect overwriting what t points to (and if t was previously allocated you will leak memory here).
Bellow you can see a correct code for what you want.
typedef struct _t {
int one;
int two;
int three;
int four;
} T;
/* Make sure we have some data to initialize */
T mydata = {0};
/*
We take a pointer to a pointer and change what the external pointer points to. */
In our example when this function is called *ppt is NULL
and t is a pointer to t in main()
*/
void second(T **ppt) {
/*
We never calculate the size of structures by hand. It can change depending on
OS and architecture. Best let the compiler do the work.
*/
*ppt = (T*)malloc(sizeof(T));
memcpy(*ppt, &mydata, sizeof(T));
}
void first(T **ppt) {
/* Make sure we don't leave dangling pointers. */
if (NULL != *ppt)
free(*ppt);
second(ppt);
}
int main() {
T *t = NULL; /* A pointer to our data */
/*
We pass a pointer to our pointer so that the function can change the value it
holds
*/
first(&t);
/* Always do an explicit return if the type of the function is not void */
return 0;
}
How to understand what is going on:
First we declare t as a pointer to a memory holding a type T and we make sure we initialize the pointer to point to NULL (which is a convention meaning that the pointer is not initialized).
We have a function that will allocate the memory for us using malloc. malloc allocates memory from the heap and returns the address of that memory. (In reality a pointer is just a variable holding an address in memory). We want to place that address in t declared in main(). To do so we need to pass to the allocating function the address of t so it can be modified. To do this we use the address of operator - &. This is why we call the function like this first(&t).
Our allocating function accepts a pointer to a pointer. This is because we want to change the address t points to. So we declared the parameter as T **ppt. It holds the address of the pointer *t in main. In the function we dereference the pointer to the pointer to get the original pointer we want to assign the address malloc returns.

Memory allocation using for loop

My Doubt is regarding only memory allocation so don't think about program output
#include<stdio.h>
int main(){
for(int i=0;i<20;i++){
char *str=malloc(sizeof(char)*6); //assuming length of each string is 6
scanf("%s",str);
insertinlinkedlist(str);
}
}
whenever i allocate memory here as shown above only the base address of char array will pass to linked list,and that is the memory block allocated for char array is inside main only and i am storing the base address of that array in str which is local to main and is passed to insetinlinkedlist
I want to ask whenever memory is allocated inside loop than why the number of
memory blocks(no of char arrays declared ) are created equal to n (number of time loop runs) since variable name is same we should be directed to same memory location
Note I have checked in compiler by running the loop all the times when loop runs memory the value of str is different
is The above method is correct of allocating memory through loop and through same variable "Is the method ensures that every time we allocate memory in above manner their will be no conflicts while memory allocation and every time we will get the address of unique memory block"
Now above doubt also creates a doubt in my mind
That if we do something like that
int main(){
for(int i=0;i<n;i++){
array[50];
}
}
then it will also create 50 array inside stack frame
malloc returns a pointer to the first allocated byte. Internally it keeps track of how much memory was allocated so it knows how much to free (you do need to insert calls to free() or you'll leak memory, by the way). Usually, it does this by allocating a little bit of memory before the pointer it gives you and storing the length there, however it isn't required to do it that way.
The memory allocated by malloc is not tied to main in any way. Currently main is the only function whose local variables have a pointer to that memory, but you could pass the pointer to another function, and that function would also be able to access the memory. Additionally, when the function that called malloc returns, that memory will remain allocated unless manually freed.
The variable name doesn't matter. A pointer is (to first approximation) just a number. Much like how running int a = 42; a = 20; is permitted and replaces the previous value of a with a new one, int *p = malloc(n); p = malloc(n); will first assign the pointer returned by the first malloc call to p, then will replace it with the return value of the second call. You can also have multiple pointers that point to the same address:
int *a = malloc(42);
int *b = malloc(42);
int *c = a;
a = malloc(42);
At the end of that code, c will be set to the value returned by the first malloc call, and a will have the value returned by the last malloc call. Just like if you'd done:
//assume here that f() returns a different value each time
//it's called, like malloc does
int a = f();
int b = f();
int c = a;
a = f();
As for the second part of your question:
for(int i=0;i<n;i++){
int array[50];
}
The above code will create an array with enough space for 50 ints inside the current stack frame. It will be local to the block within the for loop, and won't persist between iterations, so it won't create n separate copies of the array. Since arrays declared this way are part of the local stack frame, you don't need to manually free them; they will cease to exist when you exit that block. But you could pass a pointer to that array to another function, and it would be valid as long as you haven't exited the block. So the following code...
int sum(int *arr, size_t n) {
int count = 0;
for (size_t i = 0; i < n; i++) {
count += arr[i];
}
return count;
}
for(int i=0;i<n;i++){
int array[50];
printf("%d\n", sum(array, 50));
}
...would be legal (from a memory-management perspective, anyway; you never initialize the array, so the result of the sum call is not defined).
As a minor side note, sizeof(char) is defined to be 1. You can just say malloc(6) in this case. sizeof is necessary when allocating an array of a larger type.

Local Variables with Pointer Casting

One of the issues I am having is attempting to cast variables into memory to be accessed at later points.
I have an example code here that works perfectly:
unsigned int *label = (unsigned int *)malloc(sizeof(unsigned int));
label = (unsigned int * ) 0xFFAAFFAA;
Anywhere else in my code I can access this value label, and it will be pointing to 0xFFAAFFAA as its value when I try to print it.
However, if I try to assign from a variable like such:
//all of this is inside a method.. so any variables declared would be local
unsigned int localVariable = 0xFFFFFFFF;
unsigned int *label = (unsigned int *)malloc(sizeof(unsigned int));
label = &localVariable;
The result will be something crazy like: 0x7f252d6b5f00 .. which I am just assuming is some random address in memory. I know this issue is because of a local variable as that operates within a function and is not global. But I can't figure out what the syntax of this would be...
The reason I want to define the local variable is because there is other logic in the function to add and subtract from that variable.. I left it out to keep it minimal
EDIT: so I could do something like this?
unsigned int localVariable = 0xFFFFFFFF;
unsigned int *label = (unsigned int *)malloc(sizeof(unsigned int));
*label = localVariable;
It sounds like what you want here is to create a pointer to a variable in a function then have it accessible outside of the function.
The issue with your first example is that you allocate memory and assign its address to label, but then you overwrite the value of label causing you to loose the reference to the memory you just allocated. You need to dereference the pointer using the * operator to write to the memory address you just allocated.
The second example won't work because you take the address of a local variable, then that variable goes out of scope when the function returns. So the address becomes invalid.
The below example allocates space, dereferences the pointer just allocated to write to the given address, then the address is returned to the caller.
unsigned int *func()
{
// allocate space (don't cast return value of malloc)
unsigned int *label = malloc(sizeof(unsigned int));
// dereference pointer and write value to allocated memory
*label = 0xFFAAFFAA;
// pass pointer to allocated memory to the calling function
return label;
}
Keep in mind that the calling function will be responsible for calling free on the memory that is returned when it is done using it to avoid a memory leak.

Relation between pointers and the memory in the heap

I am a new C developer. I have been programming in Java for 3 years now.
I noticed the manual memory allocation I have to do in C.
However, it is still ambiguous to me when it comes to pointers and memory allocation.
I will say what I understand and please if anyone has any comment on what I have to say, please correct me.
So let's say I have:
int *a;
So what this does is creates a pointer called a that points to an integer value.
int *a = address;
If I print address, I will get the address.
Let's say I want the value, I do what we call dereferencing and
int *a = *value;
If I print value in this case, I would get the actual number stored in memory.
I noticed in the ebook I am using, that sometimes, we allocate memory in the heap.
Is it always the case? Everytime I need to use a pointer for a string for example using char*, I have to use alloc() and sizeof() to respectively allocate memory according to the size of the intended type?
OK. Pointers for the Java guy.
When you declare
int *a;
it is the same as in Java doing:
Integer a;
Java does not have pointers, but all objects are held by references. So,
Integer a = new Integer(3);
is the same as:
int *a = malloc(sizeof(int));
in C.
Now, Java does not have an & operator, and you cannot do pointer arithmetic, but references really are roughly the same otherwise.
To answer your questions:
does it always have to come from the heap?
No. In C you can point a pointer at something that is already allocated on the stack (or anywhere else in RAM, such as a DMA register for doing hardware interactions):
void f() {
int i;
int *a = &i;
*a = 3; // same as i = 3
a = (int*)0x12340000; // some address in memory, possibly screen RAM?
*a = 0xffffffff; // possibly set some colors on the screen
}
Do I have to use malloc and sizeof every time to allocate space?
If you do use malloc, then yes, you have to specify how much space you want. But you can just as easily ask the compiler to allocate the space in static data space:
void f() {
char *p = "hello";
....
}
In this case, the literal string typically becomes part of the compiled program, and is placed in a statically allocated spot at program startup by the OS.
int *a = *value;
This is incorrect unless value is declared to be an int **:
int **value;
Below is a sequence of using an int pointer with appropriate comments:
int num1; // Declare an int
int num2; // Declare a different int
int *pNum = &num1; // Declare an int pointer and set its value to the address of num1
*pNum = 6; // Set the value of num1
pNum = &num2; // Change value of int pointer to the address of num2
*pNum = 10; // Set the value of num2

Who initialize a char pointer inside a struct on the stack

Its generally known that things on the stack are not initialized by default. I tried to prove that with a struct on the stack, but unexpectedly my pointer is initialized with null, but why? What is initializing this pointer?
#include <stdio.h>
#include <string.h>
struct strustri {
int var1;
char *var2;
};
int main()
{
struct strustri test1 = {
.var1 = 12,
.var2 = "Teststring",
};
struct strustri test2;
printf("test1.var1 is %d\n", test1.var1);
printf("test2.var1 is %d\n", test2.var1);
printf("test1.var2 points to %p\n", test1.var2);
printf("test2.var2 points to %p\n", test2.var2);
return 1;
}
And this is the output on my machine (Ubuntu 12.10):
test1.var1 is 12
test2.var1 is -1271814320
test1.var2 points to 0x400634
test2.var2 points to (nil)
I ran my example multiple times. I get another value for var1 everytime, but var2 is always points to zero (null pointer)...
Nothing is initializing it.
It's just an artefact of whatever rubbish happens to be on your stack. Switch the order of the variable declarations, or add some more local variables, and you'll get a different result.
If you put your test structures in a separate function, then have another function that creates an array of char, say 200 bytes long, that you fill with some letters, and call the two functions alternating, you'll notice that your values in test2 will be different [most likely, but not 100% guaranteed - since we are dealing with "undefined behaviour", something else could happen].
when int var1 is executed to create space for test2, it has create space for itself but if you don't assign a value to it then it will show the value which was already there..
but in case of var2, it is a pointer. if pointers are not initialized then it does not point to anything, making it nil or NULL or '\0'

Resources