I'm using a double-linked list and getting some odd performance regarding edge cases when we're dealing with previous or next pointers that are null. GDB returns the following error:
Program received signal SIGSEGV, Segmentation fault.
0x0804a9c1 in DLinkDelete (delete=0xd8c9d33c) at test.c:213
213 if (prevdl && prevdl->next)
(gdb) p prevdl
$39 = (DoubleLink *) 0xdadadada
(gdb) p prevdl->next
$40 = (void *) 0x0
DoubleLink is a struct with the following format:
typedef struct
{
void *next;
void *prev;
} DoubleLink;
Why would a segmentation fault be raised here?
Presumably prevdl points to invalid memory ? Come on, does 0xdadadada really look like a valid address to you ? "It's too idiotic to be schizophrenic".
the 0xdadadada address seems very weird although it is not NULL. Maybe you're trying to read a memory that is not allowed to you.
The value:
0xdadadada
looks suspiciously unlike a real pointer value. Just because a pointer is not NULL does not mean it is valid. And if you use an invalid pointer, you will get aseg fault, or whatever.
0xdadadada looks a bit suspicious, perhaps prevdl hasn't been properly initialised? Or maybe it's been stomped on by some other code.
Maybe you should try running the test under valgrind and see if it reports anything?
0xdadadada doesn't sound like a very likely value for a valid pointer... most likely a debugging initialiser.
Specifically, it means you're accessing data that hasn't been initialized at all. Question -- it this the first attempt to use this structure?
In any case, check your initialization code; when you create the node, I'd bet the very first node, which has no previous, you aren't setting its value, but in the code above you are trying to access it.
Related
i have a problem with this function this function using a pointer without referencing it but I surprised that it working and I don't know why ptr in the Function is not referenced and function working without error if any person can explain me why it not generate error i'll be so grateful
#include<stdio.h>
int * Ret(int *x)
{
int *ptr;
*ptr = (-1*(*x));
return ptr;
}
int main(void)
{
int val = 5,op;
op = *Ret(&val);
printf("%d",op);
}
output will be -5 but I think that it must generate run time error ?
It's undefined behaviour.
Anything can happen and because of that can be a valid behaviour.
If you want to catch these problems use external tools, e.g. valgrind or a custom compiler e.g. clang with address sanitizer.
You are right in the fact that the function is doing something wrong.
The function returns a pointer to an integer which is allocated only inside the function.
The memory (the value) the pointer points to does not change at the end of the function and this is why you get the correct value. (the implementation of C allows it)
if you had more function later on, they might have override this memory and the value of 'op' might have changed
Bottom line, don't do it!
int *ptr is on the stack. Stack variables are not initialized. So it can have any value. The *ptr= assignment dereferences ptr, that is, the "any value" is taken as an address and the right hand side is stored there. If "any value", as an address, is outside the program's assigned memory, a run time error will ocur. Otherwise some memory of the program is overwritten; this error can become manifest at any later moment, can not manifest itself at all, or can give (noted or unnoted) wrong results. "Bad code", in summary.
The compiler could catch the error by flagging the use of ptr as use of an uninitialized variable.
Program was programmed in C and compiled with GCC.
I was trying to help a friend who was trying to use trying to (shallow) copy a value that was passed into a function. His the value was a struct that held primitives and pointers (no arrays or buffers). Unsure of how malloc works, he used it similar to how the following was done:
void some_function(int rand_params, SOME_STRUCT_TYPEDEF *ptr){
SOME_STRUCT_TYPEDEF *cpy;
cpy = malloc(sizeof(SOME_STRUCT_TYPEDEF));// this line makes a difference?!?!?
cpy = ptr;// overwrites cpy anyway, right?
//prints a value in the struct documented to be a char*,
//sorry couldn't find the documentation right now
}
I told him that the malloc shouldn't affect the program, so told him to comment it out. To my surprise, the malloc caused a different output (with some intended strings) from the implementation with the malloc commented out (prints our garbage values). The pointer that's passed into the this function is from some other library function which I don't have documentation for at the moment. The best I can assume it that the pointer was for a value that was actually a buffer (that was on the stack). But I still don't see how the malloc can cause such a difference. Could someone explain how that malloc may cause a difference?
I would say that the evident lack of understanding of pointers is responsible for ptr actually pointing to memory that has not been correctly allocated (if at all), and you are experiencing undefined behaviour. The issue is elsewhere in the program, prior to the call to some_function.
As an aside, the correct way to allocate and copy the data is this:
SOME_STRUCT_TYPEDEF *cpy = malloc(sizeof(SOME_STRUCT_TYPEDEF));
if (cpy) {
*cpy = *ptr;
// Don't forget to clean up later
free(cpy);
}
However, unless the structure is giant, it's a bit silly to do it on the heap when you can do it on the stack like this:
SOME_STRUCT_TYPEDEF cpy = *ptr;
I can't see why there difference in the print.
can you show the print code?
anyway the malloc causes memory leak. you're not supposed to allocate memory for 'cpy' because pointer assignment is not shallow-copy, you simply make 'cpy' point to same memory 'ptr' point by storing the address of the start of that memory in 'cpy' (cpy is mostly a 32/64 bit value that store address, in case of malloc, it will store the address of the memory section you allocated)
i am just started learning pointers in c. I have following few doubts. If i find the answers for the below questions. It Will be really useful for me to understand the concept of pointers in c. Thanks in advance.
i)
char *cptr;
int value = 2345;
cptr = (char *)value;
whats the use of (char *) and what it mean in the above code snippet.
ii)
char *cptr;
int value = 2345;
cptr = value;
This also compiles without any error .then whats the difference between i & ii code snippet
iii) &value is returning address of the variable. Is it a virtual memory address in RAM? Suppose another c program running in parallel, will that program can have same memory address as &value. Will each process can have duplicate memory address same as in other process and it is independent of each other?
iv)
#define MY_REGISTER (*(volatile unsigned char*)0x1234)
void main()
{
MY_REGISTER=12;
printf("value in the address tamil is %d",(MY_REGISTER));
}
The above snippet compiled successfully. But it outputs segmentation fault error. I don't know what's the mistake I am doing. I want to know how to access the value of random address, using pointers. Is there any way? Will program have the address 0x1234 for real?
v) printf("value at the address %d",*(236632));//consider the address 236632 available in
//stack
why does the above printf statement showing error?
That's a type cast, it tells the compiler to treat one type as some other (possibly unrelated) type. As for the result, see point 2 below.
That makes cptr point to the address 2345.
Modern operating systems isolate the processes. The address of one variable in one process is not valid in another process, even if started with the same program. In fact, the second process may have a completely different memory map due to Address Space Layout Randomisation (ASLR).
It's because you try to write to address 0x1234 which might be a valid address on some systems, but not on most, and almost never on a PC running e.g. Windows or Linux.
i)
(char *) means, that you cast the data stored in value to a pointer ptr, which points to a char. Which means, that ptr points to the memory location 2345. In your code snipet ptr is undefined though. I guess there is more in that program.
ii)
The difference is, that you now write to cptr, which is (as you defined) a pointer pointing to a char. There is not much of a difference as in i) except, that you write to a different variable, and that you use a implicit cast, which gets resolved by the compiler. Again, cptr points now to the location 2345 and expects there to be a char
iii)
Yes you can say it is a virtual address. Also segmentation plays some parts in this game, but at your stage you don't need to worry about it at all. The OS will resolve that for you and makes sure, that you only overwrite variables in the memory space dedicated to your program. So if you run a program twice at the same time, and you print a pointer, it is most likely the same value, but they won't point at the same value in memory.
iv)
Didn't see the write instruction at first. You can't just write anywhere into memory, as you could overwrite another program's value.
v)
Similar issue as above. You cannot just dereference any number you want to, you first need to cast it to a pointer, otherwise neither the compiler, your OS nor your CPU will have a clue, to what exactely it is pointing to
Hope I could help you, but I recommend, that you dive again in some books about pointers in C.
i.) Type cast, you cast the integer to a char
ii.) You point to the address of 2345.
iii.) Refer to answer from Joachim Pileborg. ^ ASLR
iv.) You can't directly write into an address without knowing if there's already something in / if it even exists.
v.) Because you're actually using a pointer to print a normal integer out, which should throw the error C2100: illegal indirection.
You may think pointers like numbers on mailboxes. When you set a value to a pointer, e.g cptr = 2345 is like you move in front of mailbox 2345. That's ok, no actual interaction with the memory, hence no crash. When you state something like *cptr, this refers to the actual "content of the mailbox". Setting a value for *cptr is like trying to put something in the mailbox in front of you (memory location). If you don't know who it belongs to (how the application uses that memory), it's probably a bad idea. You could use "malloc" to initialize a pointer / allocate memory, and "free" to cleanup after you finish the job.
Got a seg fault from my memcpy that gdb can't give me anything else on (at least beyond the simple manner that I know how to use gdb...). This thing is deeply imbedded in some code using the Berkely DB; I have taken out the only lines that should be of any use.
void *databuf;
int smallest;
databuf=malloc(2*sizeof(int));
memset(databuf,0,2*sizeof(int));
/* This next line comes from the DB structures; key.data is a void*... */
smallest=*(int *)key.data;
memcpy(databuf,(void *)smallest,sizeof(int));
To confirm the variable smallest is correct, I can run gdb and get
(gdb) print smallest
$1 = 120321
The error I recieve (in gdb) is the useless
Program received signal SIGSEGV, Segmentation fault.
0x08048efa in main (argc=4, argv=0xbffff344) at index_DB-1.1.c:128
128 memcpy(databuf,(void *)smallest,sizeof(int));
(gdb) backtrace
#0 0x08048efa in main (argc=4, argv=0xbffff344) at index_DB-1.1.c:128
The reason I am doing this is mostly because I am bastardizing the Berkley DB tutorial, but also later I want to do
memcpy(databuf+len,(void *)largest,sizeof(int));
i.e. have a void pointer databuf with first byes the smallest integer and second bytes the largest integer. What am I missing?
In this step, you are interpreting the value in smallest as a pointer:
memcpy(databuf,(void *)smallest,sizeof(int));
Since that value is almost certainly not a valid pointer, this is causing your segfault. Instead, you likely want:
memcpy(databuf, &smallest, sizeof smallest);
Unless you need smallest for some other reason though, you can just copy directly from key.data to to databuf:
memcpy(databuf, key.data, sizeof(int));
(void *)smallest
That takes the integer value of smallest and treats it as a pointer. What you meant to do was this:
(void *)&smallest
It's hard to tell what you're doing, considering the code is so awful, but this looks very suspicious:
memcpy(databuf,(void *)smallest,sizeof(int));
I believe smallest contains normal integer data, not a pointer to anything. So why are you dereferencing it? It doesn't point to anything.
You might want:
memcpy(databuf,(void *) &smallest,sizeof(int));
Also, this is suspect:
smallest=*(int *)key.data;
Is smallest guaranteed to be integer aligned?
I have run gdb, as my code show segfault. I understand that the code that give the error is
210 if (colour_s->colorlist.colorlist_id == 1)
(gdb) print colour_s
$1 = (car_colour_list_t_slot *) 0x21
(gdb) print colorlist
$2 = (car_colour_list_t *) 0x12d1a80
(gdb) print colour_s->colorlist
Cannot access memory at address 0x21
typedef struct {
int colorlist_id;
} car_colour_list_t;
typedef struct _car_colour_list_t_slot {
car_colour_list_t colorlist;
struct _car_colour_list_t_slot *next, *prev;
} car_colour_list_t_slot;
car_colour_list_t_slot *colour_s;
colour_s = (car_colour_list_t_slot *)malloc(sizeof(car_colour_list_t_slot));
car_colour_list_t *colorlist;
colorlist = (car_colour_list_t *)malloc(sizeof(car_colour_list_t));
I have already assigned those pointers memory, but when I tried to print colour_s->colorlist it fails (can not access memory at address 0x21)
Can anyone understand why this happens, although I have already assign memory to each poitner?
Thank you
The colour_s pointer is definitely invalid. There is no doubt about it. GDB is simply informing you of this fact. (Any pointer near 0x0 is invalid, and any pointer with a residue modulo 4 is invalid for your structure.) The malloc function will never return 0x21.
There are lots of ways your program can do this. They boil down to two basic types of errors in your program:
colour_s was not initialized.
colour_s was initialized, but it was accidentally overwritten by an error in a different part of your code.
there is an error in GDB or your compiler (not worth considering)
Run your program with Valgrind or set a watchpoint on colour_s. These will help you discover where the error is in your code.
As an alternative exercise, see if you can find the error just by reading your code, without running it. Read carefully. This kind of exercise will make you a better programmer.