I'm writing this program to practice C programming, this is my code:
#include <stdio.h>
#include <stdlib.h>
struct s1 {
int i;
void * p;
};
static struct s1 *dmk;
int main(void) {
int tong(int a, int b);
int (*tinh)(int,int);
struct s2 {
int num;
int (*cal)(int a, int b);
};
if(dmk->p == NULL)
{
printf("NULL ALERT\n");
}
struct s2 *cl = dmk->p;
cl->cal = tong;
tinh = ((struct s2 *)(dmk->p))->cal;
printf("tinh 2, 4 ra %d\n",tinh(2,4));
puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */
return EXIT_SUCCESS;
}
int tong(int a, int b)
{
return a + b;
}
When I compiled it, it didn't show any error or warning. But when I ran the program, the terminal told me that "core dumped" and did not show any result accept for the "NULL ALERT". Can anyone explain why I failed ? Thanks alot.
if(dmk->p == NULL)
fails as dmk is uninitialised initialised to NULL, points "no-where", so de-referencing it invokes undefined behaviour. Anything can happen afterwards.
dmk is a global (aka. static (this is not related to the static keyword!), variable, thus it is initialized to a null pointer. You do not change this value, so dkms->p dereferences a null pointer, which invokes undefined behaviour (UB).
So from here, it is speculation, as UB means anything can happen.
Apparently the printf passes, probably because the address can be read. The following write OTOH fails, generating the system messsage.
Bottom line is that what you're doing wrong is not assigning things to your various pointers before using them.
Your dmk is a global, so its initial value is NULL. You're never changing that value.
Later, you read dmk->p. You're now in Undefined Behavior (UB) territory. The program could easily have faulted right there, because you were reading from a NULL pointer.
Apparently it didn't, though, because you're seeing your NULL ALERT message, and so we continue.
Then you do this:
struct s2 *cl = dmk->p;
cl->cal = tong;
On the second line there, cl is completely indeterminate. It could be garbage, it could be NULL, whatever, because you're entered UB territory. Then you dereference it and write to the result. You could be trying to write anywhere. Writing to random pointers (or NULL pointers) tends to make core dumps and other Bad Things™ happen.
You need to actually assign values to your pointers before you use them.
You don't initialize dmk in your code. That dmk->p is NULL is pure luck. Anything could happen.
You need to allocate memory for your struct using, for instance, malloc(), and initialize the members properly.
Related
This program causes a seg fault on my UNIX machine. I narrowed the cause down to the second call of memset().
Why is this behaviour occurring? The first "chunk" of code is almost the same as the second, isn't it? Why didn't the first call of memset segfault if the second one does?
I looked over other threads concerning segfaulting memset calls, but none of them were similar to this.
In case you were wondering why I wrote such a trivial program, it's adapted from another program I've been writing that I was using to teach myself how to apply memcpy() to structures.
#include <stdio.h>
#include <stdlib.h>
typedef struct{
int x;
char text;
} FilesStruct;
int
main(int argc, char** argv)
{
FilesStruct *old_dir;
memset(old_dir,0,sizeof(FilesStruct));
old_dir->x = 3;
old_dir->text = 'c';
printf("old dir: %d,%c\n",old_dir->x,old_dir->text);
FilesStruct *new_dir;
memset(new_dir,0,sizeof(FilesStruct));
new_dir->x = 7;
new_dir->text = 'g';
printf("new dir: %d,%c\n",new_dir->x,new_dir->text);
return 0;
}
FilesStruct *old_dir;
memset(old_dir,0,sizeof(FilesStruct));
attempts to write to an uninitialised pointer. This results in undefined behaviour, including possibly a crash. Its just luck (good or bad, depending on how you look at it) that the first instance of this behaviour didn't crash.
You need to allocate memory for old_dir. The easiest way to do this is to declare it on the stack
FilesStruct old_dir;
memset(&old_dir,0,sizeof(old_dir));
or you could dynamically allocate on the heap (making sure to call free when you no longer need the object)
FilesStruct *old_dir = calloc(1, sizeof(*old_dir);
/* use old_dir */
free(old_dir);
The same applies to new_dir further down your code.
Neither old_dir nor new_dir are initialized, so this is undefined behavior. One solution would be to allocate both variables on the stack:
FilesStruct old_dir;
//...
FilesStruct new_dir;
and use the & operator to obtain the address when calling memset:
memset(&old_dir,0,sizeof(FilesStruct));
FilesStruct *old_dir;
This defines a FilesStruct pointer. It is uninitialized, so it doesn't actually point to any storage for a FilesStruct.
memset(old_dir,0,sizeof(FilesStruct));
Will tell memset to zero out whatever old_dir points at, but as the pointer is uninitialized, you get undefined behavior.
You'll need to provide storage for your pointer, e.g.
FilesStruct *old_dir = malloc(sizeof(FilesStruct));
In your case you don't really need a pointer or dynamically allocated memory, you might do
FilesStruct old_dir;
memset(&old_dir,0,sizeof(FilesStruct));
old_dir.x = 3;
old_dir.text = 'c';
printf("old dir: %d,%c\n",old_dir.x,old_dir.text);
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'
I have a question regarding this code. I write this code in my framework, and it caused the framework crashed. But when I rewrite this code below in a single file, but it works just fine. I was just wondering, is the code below is correct for memory allocation and freeing it? (especially for the part of msg->context_var.type = f;)
Thank you
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int value;
int price;
int old;
} type_t;
typedef struct {
type_t *type;
} context_t;
typedef struct {
context_t context_var;
} send_request;
void send_Message(send_request *msg)
{
type_t *f = 0;
f = malloc(sizeof(f));
msg->context_var.type = f;
msg->context_var.type->price = 1;
msg->context_var.type->value = 100;
msg->context_var.type->old =120;
printf("value of %d/n", msg->context_var.type->price);
free(f);
}
int main()
{
send_request *msg = 0;
msg = (send_request *) malloc(sizeof(send_request));
send_Message(msg);
free(msg);
return 0;
}
It's wrong.
f = malloc(sizeof(f)); /* Wrong */
f = malloc(sizeof(*f)); /* Better ? */
sizeof(f) will give you the size of a pointer on your machine; sizeof(*f) will give you the size of the object pointed to.
EDIT As requested by #Perception
When you allocate less than you need you're eliciting Undefined Behavior. Anything can happen (even the desired behavior) and it all depends on the platform, the environment (the moon phase, etc).
msg->context_var.type->value = 100; /* Writes beyond what's allocated. */
So, depending on the memory layout of the "framework" this might simply overwrite some memory and "work", or it could crash. Frankly I prefer when it crashes straight away.
You allocate an instance of context_t on the heap, and then msg->context_var.type gets the value of the resulting pointer f.
Since msg is a pointer parameter to the send_Message function, no reliable assumptions can be made about what is done with msg and its contents after your function exists. As such, when you go on to free the memory pointed to by f, you leave a dangling pointer in msg->context_var.type.
If the memory it points to is accessed after send_Message exists, there's a fair chance that you corrupt something vital (or read something crazy, like a pointer to 0xdeadbeef), as it might contain something completely different now.
Not only are you allocating wrong size (see cnicutar's answer)-- If you are attaching f to message that is passed by the framework, you probably don't want to free it before the function returns. You'll need to free it later, though-- probably through some other facility provided by the framework?
I have argument with my friend. He says that I can return a pointer to local data from a function. This is not what I have learned but I can't find a counterargument for him to prove my knowledge.
Here is illustrated case:
char *name() {
char n[10] = "bodacydo!";
return n;
}
And it's used as:
int main() {
char *n = name();
printf("%s\n", n);
}
He says this is perfectly OK because after a program calls name, it returns a pointer to n, and right after that it just prints it. Nothing else happens in the program meanwhile, because it's single threaded and execution is serial.
I can't find a counter-argument. I would never write code like that, but he's stubborn and says this is completely ok. If I was his boss, I would fire him for being a stubborn idiot, but I can't find a counter argument.
Another example:
int *number() {
int n = 5;
return &n;
}
int main() {
int *a = number();
int b = 9;
int c = *a * b;
printf("%d\n", c);
}
I will send him this link after I get some good answers, so he at least learns something.
Your friend is wrong.
name is returning a pointer to the call stack. Once you invoke printf, there's no telling how that stack will be overwritten before the data at the pointer is accessed. It may work on his compiler and machine, but it won't work on all of them.
Your friend claims that after name returns, "nothing happens except printing it". printf is itself another function call, with who knows how much complexity inside it. A great deal is happening before the data is printed.
Also, code is never finished, it will be amended and added to. Code the "does nothing" now will do something once it's changed, and your closely-reasoned trick will fall apart.
Returning a pointer to local data is a recipe for disaster.
you will get a problem, when you call another function between name() and printf(), which itself uses the stack
char *fun(char *what) {
char res[10];
strncpy(res, what, 9);
return res;
}
main() {
char *r1 = fun("bla");
char *r2 = fun("blubber");
printf("'%s' is bla and '%s' is blubber", r1, r2);
}
As soon as the scope of the function ends i.e after the closing brace } of function, memory allocated(on stack) for all the local variables will be left. So, returning pointer to some memory which is no longer valid invokes undefined behavior.
Also you can say that local variable lifetime is ended when the function finished execution.
Also more details you can read HERE.
My counter-arguments would be:
it's never OK to write code with undefined behavior,
how long before somebody else uses that function in different context,
the language provides facilities to do the same thing legally (and possibly more efficiently)
It's undefined behavior and the value could easily be destroyed before it is actually printed. printf(), which is just a normal function, could use some local variables or call other functions before the string is actually printed. Since these actions use the stack they could easily corrupt the value.
If the code happens to print the correct value depends on the implementation of printf() and how function calls work on the compiler/platform you are using (which parameters/addresses/variables are put where on the stack,...). Even if the code happens to "work" on your machine with certain compiler settings it's far from sure that it will work anywhere else or under slightly different border conditions.
You are correct - n lives on the stack and so could go away as soon as the function returns.
Your friend's code might work only because the memory location that n is pointing to has not been corrupted (yet!).
As the others have already pointed out it is not illegal to do this, but a bad idea because the returned data resides on the non-used part of the stack and may get overridden at any time by other function calls.
Here is a counter-example that crashes on my system if compiled with optimizations turned on:
char * name ()
{
char n[] = "Hello World";
return n;
}
void test (char * arg)
{
// msg and arg will reside roughly at the same memory location.
// so changing msg will change arg as well:
char msg[100];
// this will override whatever arg points to.
strcpy (msg, "Logging: ");
// here we access the overridden data. A bad idea!
strcat (msg, arg);
strcat (msg, "\n");
printf (msg);
}
int main ()
{
char * n = name();
test (n);
return 0;
}
gcc : main.c: In function ‘name’:
main.c:4: warning: function returns address of local variable
Wherever it could been done like that (but it's not sexy code :p) :
char *name()
{
static char n[10] = "bodacydo!";
return n;
}
int main()
{
char *n = name();
printf("%s\n", n);
}
Warning it's not thread safe.
You're right, your friend is wrong. Here's a simple counterexample:
char *n = name();
printf("(%d): %s\n", 1, n);
Returning pointer to local variable is aways wrong, even if it appears to work in some rare situation.
A local (automatic) variable can be allocated either from stack or from registers.
If it is allocated from stack, it will be overwritten as soon as next function call (such as printf) is executed or if an interrupt occurs.
If the variable is allocated from a register, it is not even possible to have a pointer pointing to it.
Even if the application is "single threaded", the interrupts may use the stack. In order to be relatively safe, you should disable the interrupts. But it is not possible to disable the NMI (Non Maskable Interrupt), so you can never be safe.
While it is true that you cannot return pointers to local stack variables declared inside a function, you can however allocate memory inside a function using malloc and then return a pointer to that block. Maybe this is what your friend meant?
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char* getstr(){
char* ret=malloc(sizeof(char)*15);
strcpy(ret,"Hello World");
return ret;
}
int main(){
char* answer=getstr();
printf("%s\n", answer);
free(answer);
return 0;
}
The way I see it you have three main options because this one is dangerous and utilizes undefined behavior:
replace: char n[10] = "bodacydo!"
with: static char n[10] = "bodacydo!"
This will give undesirable results if you use the same function more than once in row while trying to maintain the values contained therein.
replace:
char n[10] = "bodacydo!"
with:
char *n = new char[10];
*n = "bodacydo!"
With will fix the aforementioned problem, but you will then need to delete the heap memory or start incurring memory leaks.
Or finally:
replace: char n[10] = "bodacydo!";
with: shared_ptr<char> n(new char[10]) = "bodacydo!";
Which relieves you from having to delete the heap memory, but you will then have change the return type and the char *n in main to a shared_prt as well in order to hand off the management of the pointer. If you don't hand it off, the scope of the shared_ptr will end and the value stored in the pointer gets set to NULL.
If we take the code segment u gave....
char *name() {
char n[10] = "bodacydo!";
return n;
}
int main() {
char *n = name();
printf("%s\n", n);
}
Its okay to use that local var in printf() in main 'coz here we are using a string literal which again isn't something local to name().
But now lets look at a slightly different code
class SomeClass {
int *i;
public:
SomeClass() {
i = new int();
*i = 23;
}
~SomeClass() {
delete i;
i = NULL;
}
void print() {
printf("%d", *i);
}
};
SomeClass *name() {
SomeClass s;
return &s;
}
int main() {
SomeClass *n = name();
n->print();
}
In this case when the name() function returns SomeClass destructor would be called and the member var i would have be deallocated and set to NULL.
So when we call print() in main even though since the mem pointed by n isn't overwritten (i am assuming that) the print call will crash when it tried to de-reference a NULL pointer.
So in a way ur code segment will most likely not fail but will most likely fail if the objects deconstructor is doing some resource deinitialization and we are using it afterwards.
Hope it helps
Due to my feeble understanding of allocating type memory to pointers, the following causes a bus error on the call to barrier_create ("hi" is never printed).
typedef struct barrier barrier_t;
typedef struct barrier *barrier_p;
barrier_p test_barrier_p;
int main(int argc, char *argv[]) {
barrier_create(*test_barrier_p);
}
int barrier_create(barrier_p *barrier_pointer) {
printf("hi\n");
barrier_p old_barrier, new_barrier;
int count;
old_barrier = (barrier_p) *barrier_pointer;
new_barrier = (barrier_p) malloc(sizeof(*new_barrier));
count = pthread_mutex_init(&new_barrier->lock, NULL);
new_barrier->is_valid = VALID_BARRIER;
new_barrier->counter = 0;
new_barrier->release_flag = 0;
*barrier_pointer = new_barrier;
return HAPPY_HAPPY_JOY_JOY;
}
What am I missing or mis-typing?
barrier_create(*test_barrier_p);
Since barrier_create takes address of a barrier_p, this should be &test_barrier_p, not *test_barrier_p.
printf("hi\n");
Inaccurate test of code reachability because stdout is likely buffered; I'd recommend fprintf(stderr, "hi\n"); instead.
new_barrier = (barrier_p) malloc(sizeof(*new_barrier));
I'd say sizeof(barrier_t). Again a * in an odd place, the _p notation may not be helping your type manipulation clarity.
For pedanticism, I would check the return value of malloc. I see little point in keeping the old value unless to recover in some way from a malloc error.
What is the purpose of count?
You're dereferencing a bad pointer in your main function. To get the address of the variable, you use the address & operator, not the dereferencing * operator. Rewrite main as:
barrier_create(&test_barrier_p);
The test_barrier_p variable is a pointer to a barrier structure which is never being initialized, so it's set to NULL (since it's at file scope).
You're de-referencing it at the call from main() to barrier_create().
For help beyond that, you'll need to tell us, in English, what you're trying to achieve.
The function int barrier_create(barrier_p *barrier_pointer) takes a pointer as an argument. However, you a passing in an actual barrier_p in your main since you dereference it - barrier_create(*test_barrier_p). I think you should be passing the address like barrier_create(&test_barrier_p)