Variable Declaration in C - c

I am trying to declare a integer variable m and a pointer to integer data type n.
int m,*n;
*n=2;
printf("%d",*n);
above code works fine.
But
int *n,m;
*n=2;
printf("%d",*n);
gives segmentation fault.
please explain why?

Both versions are wrong—you just got lucky with the one that worked. You've declared a pointer but not allocated any storage for it. Try this:
int *n,m;
n=&m;
*n=2;
printf("%d",*n);
Or using malloc():
int *n;
n=malloc(sizeof(int));
*n=2;
printf("%d",*n);
free(n);

Both code segments invoke undefined behaviour, because you dereference an uninitialized pointer. When there is UB, nasal demons fly out of your nose... or your program orders pizza, or it crashes, or it works... You must alllocate memory first.
int* n = malloc(sizeof(int));
*n = 2;
free(n);
Or set it to an address of another object;;
int *n, m;
n = &m;
*n = 2;

When you declare a pointer variable, it allocates some block of space in memory. This space already contains some data left over from whatever it was used for before this program. It gives a segmentation fault because whatever data is in the pointer refers to a memory location outside of your space on the hard drive. As Armen said, you have to initialize the pointer by telling it where to point. This will replace the data currently in the pointer with the address of your variable m (or wherever you want it to point).

n is uninitialized pointer. Access to it causes error.

You are lucky the first one works at all. Both of them are accessing a non-initialized pointer.
What does "n" point to? Since it is uninitialized, it is pointing to nothing. In each case, you are assigning whatever n is pointing to the value of 2. The first will eventually lead to a nasty bug. You are lucky on the second one because it crashed right away.
Use malloc to create some memory for n to point to, and then assign it.

Related

Union as a Structure Variable in C

I have the following structures:
complex_attribute
generic_attribute
I defined a union of these two, like so:
union union_attribute{
struct complex_attribute *complex;
struct generic_attribute *generic;
};
And then i defined another structure which keeps track of the union and a code associated with it:
struct tagged_attribute{
int code;
union union_attribute *attribute;
};
Then, i defined another structure called Disk, which contains an array of pointers to tagger_attribute objects:
struct disk {
struct tagged_attribute *attribute_ptr[100];
}
Now I am trying to access the code of the tagged attribute like this:
printf("%i", disk_ptr->attribute_ptr[counter]->code);
But I am getting a segmentation fault. Is my way of accessing the structure variable "code" incorrect?
Here is all of the relevant code from where I am trying to access "code":
struct disk* construct_disk(char* name, char* serial, char* vendor, char* model, int RPM, char *raid_type, int num_args, ...){
struct disk *disk_ptr;
disk_ptr = malloc (sizeof (struct disk));
va_list ap;
va_start(ap, num_args);
int counter;
int incrementer;
//subattributes is a global variable
incrementer = subattributes[counter];
for(counter = 0; counter < num_attributes; counter++, incrementer = subattributes[counter]){
printf("Counter = %i\n", counter);
printf("incrementer = %i\n", incrementer);
if (1){
printf("Populating generic attribute");
printf("%i", disk_ptr->attribute_ptr[counter]->code);
//disk_ptr->attribute_ptr[counter]->code = GENERIC_ATTRIBUTE_TYPE;
//disk_ptr->attribute_ptr[counter]->attribute->generic = construct_generic_attribute(va_arg(ap, int));
}else{
printf("Populating complex attribute");
//struct generic_attribute* input_to_complex_attribute[incrementer];
//int stepper;
//for(stepper = 0; stepper<incrementer; stepper++){
// input_to_complex_attribute[stepper] = construct_generic_attribute(va_arg(ap, int));
//}
//disk_ptr->attribute_ptr[counter]->code = COMPLEX_ATTRIBUTE_TYPE;
//disk_ptr->attribute_ptr[counter]->attribute->complex = construct_complex_attribute(5, incrementer, input_to_complex_attribute);
}
}
va_end(ap);
return disk_ptr;
}
You aren't accessing code at all (which you should be using to check which union member is valid, of course).
You're accessing the counterth element of the attribute_ptr array, which is a pointer to a tagged_attribute and trying to dereference it (with ->). Possibly without allocating that pointer (or any of the others in that array) first, nor initialising the memory after allocation (you haven't shown anything about that... failure to allocate correctly is a likely cause of your segfault.)
Of course, this assumes disk_ptr has been allocated and initialised correctly... which you haven't shown and may not have.
As already mentioned, show all relevant code if you want a more specific answer to your question. Further, compile with warnings enabled and learn to use tools such as gdb (GNU debugger) and valgrind (for memory issues) to debug your code.
EDIT: Now that you've added code, you have allocated disk_ptr but you never allocate anything in attribute_ptr, so it's just 100 pointers pointing to arbitrary places in memory.
You are dereferencing disk_ptr->attribute_ptr[1], but that array of pointers is not initialized (the pointers point nowhere).
You have to malloc the struct tagged_attribute entries for each pointer first.
In C if a pointer is not pointing to valid memory you will have undefined behavior. One of the common things that happens is a segmentation fault as the pointer has random chunk or was initialized to zero and when you try to access the memory it is pointing to the hardware detects that you are accessing an invalid memory page. Every time you use -> you are dereferencing the pointer and run the risk of a seg fault. You should use a debugger to find the incorrect value. An alternative is to print the values before you dereference them:
printf("disk_ptr = %p\n", disk_ptr);
printf("disk_ptr->attribute_ptr[counter] = %p\n", disk_ptr->attribute_ptr[counter]);
You should place this code before the print that you shows. If disk_ptr is an invalid value the second print will fail. The first print will always succeed but you should see if it is NULL or not. If you do not see the second print that means the disk_ptr is an invalid pointer. This because in the second print disk_ptr is dereferenced via the -> operator and if it points to chunk it could (let me emphasize could) cause a seg fault (it could also overwrite some other data which might cause a seg fault later). If the second print works but the print you shows does not then disk_ptr->attribute_ptr[counter] could be the invalid pointer. Let me emphasize again because it is important. If a pointer is not pointing to a correct memory location you have undefined behavior. Dereferencing that pointer could cause a seg fault right there or could modify memory in some way such that a seg fault occurs later.

initialising a structure through pointer

Suppose we have
struct me {
int b;
};
void main() {
struct me *m1;
m1->b=3;
}
My quesrion is that , as m1 is a pointer of type me and is currently
not holding any address of variable of type me then how we can access b which is member of me
through a pointer which is not pointing to any variable of type me and if we can then which variable of type me is accesing a?
It's either
struct me m1;
m1.b = 3;
or
struct me *m1 = malloc(sizeof(struct me));
m1->b = 3;
When you deal with pointers in C, you usually need to do 3 things:
create the pointer
make sure the memory is allocated where the pointer should point
make the pointer point to that memory
Your solution only did the first of these.
The reason why your printf works, is that the actual assignment and reading still works. You were overwriting some random memory in your process, this time without any disastrous result. But it's pure "luck". You could have ended up with a segmentation fault as well.
1) You must allocate space for the object you're pointing to first
2) Then - and only then - can you assign the value m1->b = 3
void main()
{
struct me *m1=malloc(sizeof(struct me)); //here allocating the memory first
m1->b=3;
//do what you want to do
free(m1); //once you allocate the memory, you have to free it after your job is done
}
If you do not allocate memory and access (like you have done), you are accessing a part of memory where m1 points to. It will compile fine. But if m1 has a value outside the segment of your code, it will give rise to segmentation fault. Also if it is within your segment, it may overwrite other values. So it is always desirable to allocate the memory before using it.

Unable to understand Memory allocation of structure

Consider following C code -
typedef struct node
{
int data;
}node;
int main()
{
node *temp;
temp->data=100;
printf("%d",temp->data);
return 0;
}
It gives Segmentation fault on line containing temp->data=100; because (I think) I haven't allocate memory for it. So, there is nothing such as temp->data.But, when I try with -
int main()
{
node *temp,*n;
n=(node*)malloc(sizeof(node));
n->data=100;
temp->data=n->data;
printf("%d",temp->data);
retrun 0;
}
It gives proper output 100.
I haven't allocate memory where temp will point. But still I am copying n->data to temp->data. How ??
The temp pointer takes some garbage value as its not initialised. By chance temp has a garbage value which may happen to be legal address for your program so it runs. If garbage value has illegal adress it will generate segment fault.
You're lucky.
Local variables are not initialized automatically, so when the program begins, both temp and n contain whatever values happen to be on the stack. Next, memory is allocated and n is set to point to it. The value 100 is stored in the data member of the structure.
But temp is still uninitialized, so the value 100 is copied into an unspecified area of memory. Depending on where that memory happens to be, the program may segfault, or it may simply corrupt memory that it doesn't own.
That you haven't got a segfault in temp->data=n->data; is just coincidence. temp is not initialized and hence it points into the digital nirvana.
When you've called malloc you've allocated sizeof node bytes (in reality it may be even a little more) and then you have full memory access to the block pointed to by n.
In general you should call malloc in this way:
node *n;
n = malloc(sizeof *n);
without a cast
with sizeof *n instead of sizeof <datatype>. If you change the datatype (for example you have a typo and instead of typedef .... node you've writen typedef ... nhode. Then you only have to change the declarations of the variables and the rest of the code doesn't have to be changed at all.
Your first code is also right just "temp" is pointing to a garbage value so you have to initialized that.
temp=(node *)malloc(sizeof(node));
Your right on the first part, it segfaults because node* temp isn't pointing anywhere (well, somewhere, but not to allocated memory).
I don't know why the second one "works". I suspect it only appears to work, in that it's not crashing. But since temp was never initialized, who know where it's sticking that '100'. Maybe just hanging around to crash later. Either way, writing to unitialized memory isn't a good idea ;-0

What could be the possible reason behind the warning which comes up when the following piece of code is compiled

This is a simple piece of code which i wrote to check whether it is legitimate to return the address of a local variable and my assumptions were proved correct by the compiler which gives a warning saying the same:
warning: function returns address of local variable
But the correct address is printed when executed... Seems strange!
#include<stdio.h>
char * returnAddress();
main()
{
char *ptr;
ptr = returnAddress();
printf("%p\n",ptr);
}
char * returnAddress()
{
int x;
printf("%p\n",&x);
return &x;
}
The behaviour is undefined.
Anything is allowed to happen when you invoke undefined behaviour - including behaving semi-sanely.
The address of a local variable is returned. It remains an address; it might even be a valid address if you're lucky. What you get if you access the data that it points to is anyone's guess - though you're best off not knowing. If you call another function, the space pointed at could be overwritten by new data.
You should be getting warnings about the conversion between int pointer and char pointer - as well as warnings about returning the address of a local variable.
What you are trying to do is usually dangerous:
In returnAddress() you declare a local, non-static variable i on the stack. Then you return its address which will be invalid once the function returned.
Additionally you try to return a char * while you actually have an int *.
To get rid of the warning caused by returning a pointer to a local var, you could use this code:
void *p = &x;
return p;
Of course printing it is completely harmless but dereferencing (e.g. int x = *ptr;) it would likely crash your program.
However, what you are doing is a great way to break things - other people might not know that you return an invalid pointer that must never be dereferenced.
Yes, the same address is printed both times. Except that, when the address is printed in main(), it no longer points to any valid memory address. (The variable x was created in the stack frame of returnAddress(), which was scrapped when the function returned.)
That's why the warning is generated: Because you now have an address that you must not use.
Because you can access the memory of the local variable, doesn't mean it is a correct thing to do. After the end of a function call, the stack pointer backtracks to its previous position in memory, so you could access the local variables of the function, as they are not erased. But there is no guaranty that such a thing won't fail (like a segmentation fault), or that you won't read garbages.
Which warning? I get a type error (you're returning an int* but the type says char*) and a warning about returning the address of a local variable.
The type error is because the type you've declared for the function is lies (or statistics?).
The second is because that is a crazy thing to do. That address is going to be smack in the middle (or rather, near the top) of the stack. If you use it you'll be stomping on data (or have your data stomped on by subsequent function calls).
Its not strange. The local variables of a function is allocated in the stack of that function. Once the control goes out of the function, the local variables are invalid. You may have the reference to the address but the same space of memory can be replaced by some other values. This is why the behavior is undefined. If you want reference a memory throughout your program, allocate using malloc. This will allocate the memory in heap instead of stack. You can safely reference it until you free the memory explicitly.
#include<stdio.h>
#include<stdlib.h>
char * returnAddress();
main()
{
char *ptr;
ptr = returnAddress();
printf("%p\n",ptr);
}
char * returnAddress()
{
char *x = malloc(sizeof(char));
printf("%p\n",x);
return x;
}

Pointer assignment Problem

When i run the above program in gcc complier(www.codepad.org) i get the output as
Disallowed system call: SYS_socketcall
Could anyone please clear why this error/output comes?
int main() {
int i=8;
int *p=&i;
printf("\n%d",*p);
*++p=2;
printf("\n%d",i);
printf("\n%d",*p);
printf("\n%d",*(&i+1));
return 0;
}
what i have observed is i becomes inaccessible after i execute *++p=2;WHY?
When you do *p = &i, you make p point to the single integer i. ++p increments p to point to the "next" integer, but since i is not an array, the result is undefined.
What you are observing is undefined behavior. Specifically, dereferencing p in *++p=2 is forbidden as i is not an array with at least two members. In practice, your program is most likely attempting to write to whatever memory is addressed by &i + sizeof(int).
You are invoking undefined behaviour by writing to undefined areas on the stack. codepad.org has protection against programs that try to do disallowed things, and your undefined behaviour program appears to have triggered that.
If you try to do that on your own computer, your program will probably end up crashing in some other way (such as segmentation fault or bus error).
The expression*++p first moves the pointer p to point one int forward (i.e. the pointer becomes invalid), then dereferences the resulting pointer and tries to save the number 2 there, thus writing to invalid memory.
You might have meant *p = 2 or (*p)++.
Your code accesses memory it does not own, and the results of that are undefined.
All your code has the right to do as it is currently written is to read and write from an area memory of size sizeof(int) at &i, and another of size sizeof(int*) at &p.
The following lines all violate those constraints, by using memory addresses outside the range you are allowed to read or write data.
*++p=2;
printf("\n%d",*p);
printf("\n%d",*(&i+1));
Operator ++ modifies its argument, so the line *++p=2; assigns 2 to a location on the stack that probably defines the call frame and increments the pointer p. Once you messed up the call frame - all bets are off - you end up in corrupt state.

Resources