Whats wrong with this C code lines
char *string()
{
char *text[20];
strcpy(text,"Hello world");
return text;
}
I was poor at pointers and I have seen this in some previous paper.
Can't able to solve.
It doesn't compile, since it treats an array of character pointers as a single array of characters.
The variable declaration line should be:
char text[200];
With that fix done, it's still broken for the reason you're probably interested in: it returns the address of a local variable (the text character array) which goes out of scope as the function returns, thus making the address invalid. There are two ways around that:
The easiest is to make the array static, since that makes it live for as long as the program runs.
You can also switch to dynamic (heap) memory by using malloc(), but that transfers ownership to the caller and requires a call to free() or memory will leak if this function gets called a lot.
Also, as a minor point, its name is in a reserved name space (user programs cannot define functions whose names begin with str). Also, a function taking no arguments should be declared as (void) in C, an empty pair of parentheses does not mean the same thing.
This code will not compile because you are trying to make an array of pointers.
In simple words if you want to handle string using pointer you can do using following:
char *str="HELLO WORLD";
And if you want to handle string using char array you have to remove value at address operator(*).
here it is:
char text[20];
then you can perform your function.
Still there is error as the Scope of the text is only valid inside the function so if you want to pass address and retain the value make it static
static char text[20];
return text;
Related
I have a global variable declared char* global=NULL and a function where I parse a separate string but copy its value into the global variable. Essentially copying the second word in the string into the global variable. And at the end of this function in the last print statement it prints out the global variable correctly, which again contains the second word of the string.
void parsestring(char* s, char** ssp){
int i;
char st[30];
strcpy(st,s);
printf("String st after copy is %s",st);
char* first=strtok(st," ");
char* second=strtok(NULL," ");
printf("\nstring s at the end is %s\n",s);
global=second;
printf("\nsecond after assigning to blobal is is %s\n",second);
printf("\n global at end of parse function is %s",global);
}
But when I call this global variable from a different function and test print its value, it only prints part of the string, not the entirety of it like it does at the end of the above function.
I know what i'm doing isn't optimal but I don't get why the global variable changes when called later in my program.
in your function you assign global to point into a buffer on the stack.
when the function exists, st is no longer yours.
change global to be a buffer by itself.
No, you cannot do that safely:
char st[30];
char * second=strtok(NULL," ");
global = second;
The first line above creates a local variable in the function (which you copy some string into).
The second line gives you an address within that string, and the third line assigns that address to your global variable.
Unfortunately for you, the st object goes out of scope at the end of the function so you are not allowed to use it by, for example, dereferencing an address that points into it.
What's probably happening (although this is irrelevant) is that the area of the stack where st is stored is being reused somehow, "damaging" the string at which the global variable points.
I say "irrelevant" since the word "stack" appears approximately zero times in the ISO C standard. The basic rule is that you need to follow what the standard says, or bad things may happen. What those bad things are is dependent totally on the implementation :-)
In terms of fixing it, you basically need to make sure the information goes somewhere that won't go out of scope before you need to use it. That could be, for example, making global a character array (much like st) rather than a pointer, and strcpying to it.
Or, having your function allocate memory that will survive function exit, such as with (see here if your implementation doesn't provide a strdup):
global = strdup(second);
Just remember to free that memory once you're done with it.
This question is not an exact duplicate of this. The most popular answer here says that it was not guaranteed that the memory location would be preserved but by accident it did. Where I got this piece of code from, it says clearly that the string variable will be preserved.
Consider the following code:
#include<stdio.h>
char *getString()
{
char *str = "abc";
return str;
}
int main()
{
printf("%s", getString());
getchar();
return 0;
}
This code compiles and runs without any errors.
The pointer char* str is not defined as a static variable. Yet the variable seems to be preserved even after the function returns.
Please explain this behavior.
I do not understand why this question got a negative vote even though it's not answered yet or marked as duplicate.
char *getString() ... char *str = "abc";
You are making some confusion. getString() creates a variable in the stack, and makes it point to a literal string. That literal can be anywhere, and will stay always there; depending on the compiler, it can be in RAM initialized at startup, or it can be in read-only memory. OK: If it is in RAM, perhaps you can even modify it, but not in normal (legal) ways - we should ignore this and think at the literal as immutable data.
The point above is THE point. It is true that the string "is preserved". But it is not true that an automatic variable is preserved - it can happen, but you should not rely on that, it is an error if you do it. By definition, an automatic variable gets destroyed when the function returns, and be sure that it happens.
That said, I don't see how you can say that the variable is preserved. There is no mechanism in C to peek at local variables (outside the current scope); you can do it with a debugger, especially when the active frame is that of getString(); maybe some debugger lets you to look where you shouldn't, but this is another matter.
EDIT after the comment
Many compilers create auto (local) variables in the stack. When the function returns, the data on the stack remains untouched, because clearing/destroying the stack is made by simply moving the stack pointer elsewhere. So the affirmation "the variable seems to be preserved" is correct. It seems because actually the variable is still there. It seems because there is no legal way to use it. But even in this situation, where the variable is still there but hidden, the compiler can decide to use that room for something else, or an interrupt can arrive and use that same room. In other words, while the auto variable is in scope it is guaranteed to be "preserved", but when it falls out of scope it must be considered gone.
There are situation where one can write code that refers to variables fallen out of scope: these are errors that the compiler should (and sometimes can) detect.
I said that often auto variables go in the stack. This is not always true, it depends on architecture and compiler, but all the rest is true and it is dictated by the language rules.
The address of str may change but the thing it points to (once initialised) will not.
Note that in this simple example you probably won't see changes. If you call getString a few times from different stack depths and show &str you will see what I mean.
char *getString()
{
char *str = "abc";
printf("%p", &str);
return str;
}
int main()
{
printf("%s", getString());
stackTest();
getchar();
return 0;
}
void stackTest()
{
char blob[200];
int x=0;
printf("%s", getString());
}
*(I have not tested this and my unused stack variables might get optimised away depending on your compiler & settings)
C 2011 (draft N1570) clause 6.4.5, paragraph 6 describes how a string literal in source code becomes a static object:
The multibyte character sequence is then used to initialize an array of static storage duration and length just sufficient to contain the sequence. For character string literals, the array elements have type char, and are initialized with the individual bytes of the multibyte character sequence.
Thus, in char *str = "abc";, str is initialized to point to a static array containing the characters a, b, and c, and a null character.
Then return str; returns the value of this pointer.
Finally, printf("%s", getString()); passes the value of the pointer to printf. At this point, the str object is gone (in the C model of computation). It no longer exists. We have the value it was used to hold, but the str object itself is gone. However, the value points to a static object, the array of characters, and printf reads that array and prints it.
So, the title of your question is incorrect. The non-static pointer variable declared inside the function was not preserved. All that was preserved was the static array of characters and its address.
what is the correct way to define a string in C?
using:
char string[10];
or
char *string="???";
If I use an array, I can use any pointer to point to it and then manipulate it.
It seems like using the second one will cause trouble because we didn't allocate memory for that. I am taught that array is just a pointer value, I thought these two are the same before.
Until I did something like string* = *XXXX, and realize it didn't work like a pointer.
As #affenlehrer points out, how you "define" a string depends on how you want to use it. In reality, 'defining' a string in C really just amounts to putting it in quotes somewhere in your program. You should probably read more about how memory works and is allocated in C, but if you write:
char *ptr = "???"
What happens is that the compiler will take the string "???" (which is really four bytes of data, three '?'s followed by one zero byte for the NUL terminator). It will insert that at some static place in your program (in something called the .bss segment), and when your program starts running, the value of ptr will be initialized to point to that location in memory. This means you have a pointer to four bytes of memory, and if you try to write outside of those bytes, your program is doing something bad (and probably violating memory safety).
On the other hand, if you write
char string[10];
Then this basically tells the compiler to go allocate some space in your program of 10 bytes, and make the variable 'string' point to it. It depends where you put this: if you put it inside a function, then you will have a stack allocated buffer of 10 bytes. If you manipulate this buffer inside a function, and then don't do anything with the pointer afterwards, you're all fine. However, if you pass back the address of string -- or use the pointer in any way -- after the function returns, you're in the wrong. This is because, after the function returns, you lose all of the stack allocated variables.
There are even more ways to create strings in C (e.g. using malloc). What is your usecase? Basically you need a place in memory where the data is stored (on the stack, on the heap, static as in your second example) and then a character pointer to the first character of your string. Most string related functions will "see" the end of the string by the trailing '\0', in some other cases (mostly general purpose data related functions) you also have to provide the length of the string.
I'm trying to write a simple C program on Ubuntu using Eclipse CDT (yes, I'm more comfortable with an IDE and I'm used to Eclipse from Java development), and I'm stuck with something weird. On one part of my code, I initialize a char array in a function, and it is by default pointing to the same location with one of the inputs, which has nothing to do with that char array. Here is my code:
char* subdir(const char input[], const char dir[]){
[*] int totallen = strlen(input) + strlen(dir) + 2;
char retval[totallen];
strcpy(retval, input);
strcat(retval, dir);
...}
Ok at the part I've marked with [*], there is a checkpoint. Even at that breakpoint, when I check y locals, I see that retval is pointing to the same address with my argument input. It not even possible as input comes from another function and retval is created in this function. Is is me being unexperienced with C and missing something, or is there a bug somewhere with the C compiler?
It seems so obvious to me that they should't point to the same (and a valid, of course, they aren't NULL) location. When the code goes on, it literally messes up everything; I get random characters and shapes in console and the program crashes.
I don't think it makes sense to check the address of retval BEFORE it appears, it being a VLA and all (by definition the compiler and the debugger don't know much about it, it's generated at runtime on the stack).
Try checking its address after its point of definition.
EDIT
I just read the "I get random characters and shapes in console". It's obvious now that you are returning the VLA and expecting things to work.
A VLA is only valid inside the block where it was defined. Using it outside is undefined behavior and thus very dangerous. Even if the size were constant, it still wouldn't be valid to return it from the function. In this case you most definitely want to malloc the memory.
What cnicutar said.
I hate people who do this, so I hate me ... but ... Arrays of non-const size are a C99 extension and not supported by C++. Of course GCC has extensions to make it happen.
Under the covers you are essentially doing an _alloca, so your odds of blowing out the stack are proportional to who has access to abuse the function.
Finally, I hope it doesn't actually get returned, because that would be returning a pointer to a stack allocated array, which would be your real problem since that array is gone as of the point of return.
In C++ you would typically use a string class.
In C you would either pass a pointer and length in as parameters, or a pointer to a pointer (or return a pointer) and specify the calls should call free() on it when done. These solutions all suck because they are error prone to leaks or truncation or overflow. :/
Well, your fundamental problem is that you are returning a pointer to the stack allocated VLA. You can't do that. Pointers to local variables are only valid inside the scope of the function that declares them. Your code results in Undefined Behaviour.
At least I am assuming that somewhere in the ..... in the real code is the line return retval.
You'll need to use heap allocation, or pass a suitably sized buffer to the function.
As well as that, you only need +1 rather than +2 in the length calculation - there is only one null-terminator.
Try changing retval to a character pointer and allocating your buffer using malloc().
Pass the two string arguments as, char * or const char *
Rather than returning char *, you should just pass another parameter with a string pointer that you already malloc'd space for.
Return bool or int describing what happened in the function, and use the parameter you passed to store the result.
Lastly don't forget to free the memory since you're having to malloc space for the string on the heap...
//retstr is not a const like the other two
bool subdir(const char *input, const char *dir,char *retstr){
strcpy(retstr, input);
strcat(retstr, dir);
return 1;
}
int main()
{
char h[]="Hello ";
char w[]="World!";
char *greet=(char*)malloc(strlen(h)+strlen(w)+1); //Size of the result plus room for the terminator!
subdir(h,w,greet);
printf("%s",greet);
return 1;
}
This will print: "Hello World!" added together by your function.
Also when you're creating a string on the fly you must malloc. The compiler doesn't know how long the two other strings are going to be, thus using char greet[totallen]; shouldn't work.
SOLVED See bottom of question for solution.
I'm having trouble with passing on a String argument to my function, and am getting a segmentation fault when the function is called. The program takes in a command line input and passes on the file provided to the function after validation.
My function code goes like this:
char *inputFile; //
inputFile= argv[2];
strcpy(inputFile, argv[2]);
compress(inputFile){
//file open and creation work bug-free
//compression action to be written
void compress(char inputFile){
//compression code here
}
When the function is called, a segfault is thrown, and the value of inputFile is 0x00000000, when prior to the function call, it had a memory location and value of the test file path.
Some of the variations I've tried, with matching function prototypes:
compress(char *inputFile)
compress (char inputFile[])
I also changed the variable.
Why is a variable with a valid memory address and value in the debugger suddenly erase when used as a parameter?
Edit 1:
Incorporating suggestions here, I removed the inputFile= argv[2] line, and the debugger shows the strcpy function working.
However, I've tried both compress(char *inputFile) per Edwin Buck and compress(argv[2]) per unwind, and both changes still result in Cannot access memory at address 0xBEB9C74C
The strange thing is my file validation function checkFile(char inputFile[]) works with the inputFile value, but when I pass that same parameter to the compress(char inputFile[]) function, I get the segfault.
Edit 2- SOLVED
You know something is going on when you stump your professor for 45 min. It turns out I had declared the file read buffer as a 5MB long array inside the compress() method, which in turn maxed out the stack frame. Changing the buffer declaration to a global variable did the trick, and the code executes.
Thanks for the help!
You shouldn't be writing into memory used to hold argv[2].
You don't seem to quite understand how strings are represented; you're copying both the pointer (with the assignment) and the actual characters (with the strcpy()).
You should just do compress(argv[2]); once you've verified that that argument is valid.
First, to copy something from argv[2] to somewhere else, you need some memory for "that somewhere else". You could allocate the memory based on the size of argv[2] but for our simple example, a very large fixed size buffer will do.
char inputfile[2048];
It looks like you tried to do this by the assignment operator, which doesn't really do what you intended.
// this is not the way to what you seek, as it doesn't create any new memory for inputfile
char* inputfile = argv[2];
in passing the inputfile variable to a procedure, you want to pass much more than a single character, so void compress(char inputfile) is not an option. That leaves
compress(char *inputFile) // I prefer this one
compress (char inputFile[])
which both work, but in my experience the first is preferred, as some older compilers tend to make distinctions between pointer and array semantics. These compilers have no issues casting an array to a pointer (which is required as part of the C language specification); however, casting a pointer to an array gets a bit messy in such systems.
You've not allocated any memory for the char * to use. All you've done with char *inputfile is allocated a pointer.