Local character array in function retains its value from previous calls - c

The first call to printf in the number() function prints the string that was in
token[] at the end of its last call. Can anyone explain the reasoning behind this?
I deleted most of the function commands that are not related to the string. If I needed to provide more code let me know.
PS : If I replace the token array with a char * and dynamically store and free the address I have no such issue
void number(FILE *fp, FILE *fo, char ch)
{
char token[100],*tmp; //characters read are saved here
State currentState = S0;
State prevState;
int i,counter = 0;
printf("THE PREVIOUS TOKEN = %s\n\n",token);
while(1)
{
switch (currentState)
{
case S0 :
{
...
}
case S1 :
{
...
}
case S2 :
{
...
}
case S3 :
{
...
}
case S4 :
{
...
}
case S5 :
{
...
}
case INTEGER :
{
...
}
case FLOAT :
{
...
}
case BAD :
{
dbg(" BAD\n");
prevState=BAD;
fprintf(fo,"+Error! Invalid syntax for an integer or float\n");
tmp=avoidchars(fp,ch);
if(tmp)
{
printf("Unknown token : %s\n\n",strcat(token,tmp));
free(tmp);
}
break;
}
}
if ( ( currentState==GOOD ) || ( currentState==BAD ) && ( prevState == BAD ) )
break;
if( currentState != INTEGER && currentState != FLOAT && currentState != BAD)
{
token[counter] = ch;
ch=fgetc(fp);
}
counter++;
}
}

Printing an uninitialized variable is undefined behavior, so you are essentially asking "how undefined is undefined behavior".
There are no guarantees of what will happen when you print uninitialised data: you might get garbage, you might get something that seems to make sense, you could get a program crash. You might get something printed that makes sense today and have the program crash tomorrow. The program might work fine on your machine but crash at your customer's machine.
There are no guarantees and no predictable behavior.
Behind the scenes of your specific system, it is likely that the array is stored on the stack. If you are lucky, that area of the stack is not modified between function calls, why it might seem as the memory is preserved. It is a bad idea to design a program which relies on luck though. If you actually need to preserve the array, it needs to be declared static, which will also force an initialization to a predictable value.

Uninitialized non-static local variables have an indeterminate value, doing just about anything with such a variable, except to initialize it, leads to undefined behavior. You should simply not do it.
But to explain the behavior here, think about that the compiler doesn't initialize these variables for you, they are after all uninitialized. However, if you call a function multiple times after each other this non-initialization policy simply means that the memory will stay the same between calls. If you call functions that have their own local variables which they modify between the calls to your function, then the second call to your function will have your local variables contain the value from the previous call to the other function.
Try for example
number(...);
printf("%s %s %s %s %s\n", "foo", "bar", "flux", "blam", "foblax");
number(...)
Now if you print out the token array in the second call (technically undefined behavior), the contents will be quite different from the contents left by the previous number call.

Related

Return from void function to another void function

void reserve(int x)
{
stream = begin;
if (begin == NULL)
{
begin = stream = (struct room*)malloc(sizeof(struct room));
details();
stream->following = NULL;
printf("\n\t room booking is successful!");
x = stream->room_period;
printf("\n\t your room period is: period-%d", x);
stream->room_period = x;
return;
}
After running details(), will the program automatically continue to run or some words need to be added ??
If the function detals() terminate (returns) then the following line in reserve() will run which in this case is:
stream->following = NULL;
details presumably sets the global variable stream. Otherwise it's undefined behavior as malloc() does not initialize the memory being allocated. I suggest you avoid global variables if possible and instead pass them those variables as arguments:
details(&stream);
In C we don't cast void * and I suggest you use the variable rather than the type as argument to sizeof:
begin = stream = malloc(sizeof *begin);
You should check the return value from malloc(). It will return
NULL on failure and this will cause the following stream->following to segfault.
Not sure why you read a variable then write it back again to the same place. As x is an argument whatever you assign to it will be discard when the function returns. At least in this sample x isn't serving any purpose and could just be eliminated.
x = stream->room_period;
printf("\n\t your room period is: period-%d", x);
stream->room_period = x;
Maybe you just want to do this instead?
printf("\n\t your room period is: period-%d", stream->room_period);
Your function is missing a } so this will not compile as is.
A void functions doesn't return a value to its caller, but it returns execution.
So the code following the call todetails() will run once (and if) it returns.
If the function details() calls exit() or a similar function, then execution will not return and your process will terminate.
Aside:
Casting the result of malloc() is redundant and may hide a bug.
Assuming malloc() can not fail is very optimistic and risks undefined behaviour. Check its return value.

Issue with returning char pointer from function

My code, which gets called when you type "recent":
char* runRecent() {
FILE *ffp;
ffp = fopen("bash.txt","r");
char line[MAXLINE];
int fileItCount = 0;
for (int i = 0 ; i < numLinesinFile ; i++) {
fgets(line, sizeof(line), ffp);
if (fileCounter - 2 < 0){
printf("No recent commands exist.\n");
exit(EXIT_FAILURE);
}
if (i == (numLinesinFile - 2) && i >= 0) {
printf("Previous command: %s\n",line);
char * lineRet = strdup(line);
printf("line ret: %s\n",lineRet); //output: correct, something along the lines of "ls" or "ls -a"
printf("line ret: %d\n",&lineRet); //output: 1528174960
return lineRet;
}
}
}
The lineRet then gets passed to a function:
start(runRecent());
Where the function declaration looks like:
void start(char inputBuf[]){
printf("input is %s\n",inputBuf); //prints the command "recent" instead of the previous command that was executed
}
Why is this returning the current command instead of the previous one?
Your code has many issues,
The function does not always return a value, which can lead to undefined behavior in case the function never reaches the return statement. It is very clear why this could be the cause so I will not explain it in detail.
You can just add a default return like return NULL; at the end of the function, but then you have to check for NULL before passing the result to printf().
It also invokes undefined behavior here
printf("line ret: %d\n", &lineRet);
one of the possible explanations of your observed behavior is undefined behavior, the right way to print a pointer is
printf("line ret: %p\n", (void *) &lineRet);
anything else is considered undefined behavior by the standard.
Not checking that strdup() did not return a NULL poitner, which can happen if there is no available memory. This is very unlikely the problem, but you must check if you want your program to work under any conditions.
Not checking that fopen() did not return NULL, which can be the case when for example the file is not readable to the current user or it does not exist at all, in any case when it's not possible to open it.
start(runRecent()); automatically causes a memory leak, you don't need to free every single malloc() because memory will be released automatically when the program ends. But a few mistakes like this and you will be in serious trouble, specially because you don't check if strdup() returned a non-NULL pointer.
It turns out that it's not so hard to write a program that will eat all the system available memory, a tiny memory leak an a few minutes running are sufficient for it to happen.
NOTE: Enable compiler warnings and you would both, not ask this kind of question ever and learn more about the c language just by simple induction.

Compare strings

Thanks! Works perfectly now. Java has made me stupid :(
I am having some difficulty comparing strings in C. I get correct output when I don't use my isMorse function, but when I use it the output becomes inaccurate and displays random characters. As far as I can tell, the variable "morse" is actually changed when strcmp is called on it. I am thinking that it has to do with "morse" not being a constant, but I am unsure of how to remedy it.
Thanks!!
char *EnglishToMorse(char english)
{
static char *morse;
int i;
for (i = 0; i < LOOKUP_SIZE; i++)
{
if (lookup[i].character == english)
{
morse = lookup[i].morse;
return morse;
}
}
morse = &english; // Problem was here!!!
return morse;
}
I have a little guess. The function EnglishToMorse() might be returning a pointer to memory from the stack. If so, running another function after EnglishToMorse() will alter that memory. This would be due to a mistake in EnglishToMorse() -- declaring a local array of char and returning a pointer to it.
Without seeing the code for EnglishToMorse(), this is just a stab in the dark. You could provide us more code to look at, and win.
You have a static variable in EnglishToMorse, but it's the wrong one. There's no need for morse to be static -- you simply return it. But you do need english to be static -- rather than on the stack -- since you return its address. Also, it needs to be a NUL-terminated string. Do something like
char *EnglishToMorse(char english)
{
static char save_english[2]; /* initialized to 0's */
int i;
for (i = 0; i < LOOKUP_SIZE; i++)
if (lookup[i].character == english)
return lookup[i].morse;
save_english[0] = english;
return save_english;
}
Note, however, that the caller of EnglishToMorse must use the result or save it before EnglishToMorse is called again, since the second call may overwrite static_english.
The reason your morse variable appears to change is because it points to an area on the stack. The reason it points to an area on the stack is because you assigned it the address of your parameter english, which got pushed onto the stack when you called your function then popped off the stack once the function completed.
Now your morse variable will point to whatever memory takes that same location on the stack, which will constantly change throughout the lifetime of your program.
In my opinion, the best way to fix this problem would be to return a NULL pointer from EnglishToMorse if the character is not A-Z... then check for the NULL pointer in your isMorse function. After all, it's good practice to check for NULL pointers in code.
char* EnglishToMorse(char english)
{
int i;
english = toupper(english);
for (i = 0; i < LOOKUP_SIZE; i++)
{
if (lookup[i].character == english)
return lookup[i].morse;
}
return NULL;
}
int isMorse(char* morse)
{
int i;
/* Check for NULL, so strcmp doesn't fail. */
if (morse == NULL) return 0;
for (i = 0; i < LOOKUP_SIZE; i++)
{
if(strcmp(morse, lookup[i].morse) == 0)
return 1;
}
return 0;
}
It looks like the problem is likely in this function:
char *EnglishToMorse(char english) {
static char *morse;
// ...
morse = &english;
return morse;
}
You are returning the address of a parameter (english) that's passed into the function. This parameter ceases to exist after the function returns (and before the caller gets a chance to actually see the value). It appears as though you've attempted to fix this by declaring the morse variable static, but this only makes the morse variable itself static, not whatever it points to.
Also, strings in C must be terminated with a NUL character. By returning a pointer to a single character (as in english), there is no guarantee that the next byte in memory is or is not a NUL character. So the caller, who is expecting to see a NUL-terminated string, may get more than they bargained for.
char *EnglishToMorse(char english)
and
morse = &english;
are the problem.
You should never return a pointer to a local variable or a function parameter.

If-else problem

I'm learning queues and I came across this piece of code. It's from a book, so I can't post the whole code here but what I'm posting will be sufficient. More than a problem, I just want to confirm that whether my understanding of this code is correct or not.
In the function, delete_ap(), the 'if' statement calls qretrieve() function and stores its return value in pointer 'p'.
My problem is: If the value returned is not NULL, then too the 'if' statement is executed, isn't it?
So a value is still stored in 'p' and we can just print this value without using an 'else' statement as used in this example.
Thanks!
/* Delete an appointment from the queue. */
void delete_ap(void)
{
char *p;
if((p=qretrieve()) ==NULL) return;
printf("%s\n", p); <--Problem is in this line and the one above it.
}
/* Retrieve an appointment. */
char *qretrieve(void)
{
if(rpos==spos) /* spos:holds the index of the next free storage location.
rpos:holds the index of the next item to retrieve.*/
{
printf("No more appointments.\n");
return NULL;
}
rpos++;
return p[rpos-1];
}
This is the same as:
char *p = qretreive(); // <-- will always execute
if(p==NULL)
return; // <-- will not execute the next line if p is invalid
printf("%s\n", p);
The return statement is used instead of putting the rest of the function in an else block.
That is, the execution will only reach printf if p != NULL.
Note: Many people argue that returns in the middle of the code makes the code hard to read and prone to bugs due too missing cleanup that is usually done at the end of the method.

Returning local data from functions in C and C++ via pointer

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

Resources