Pass a string to a function in C - c

I have the following code:
#include <stdio.h>
char * lookLine (FILE *fichero)
{
char p[25];
fgets (p, sizeof (p), fichero);
return p;
}
int main (void) {
printf ("%s\n", lookLine (fopen ("suma.c", "r")));
return 0;
}
And I get the following output:
#��x�
Not nice. My intention is to print out the first line of the file whose name "suma.c". It should print out the following:
#include <stdio.h>
Nevertheless, if I print out the content of p string into the same lookFile function, it does it fine:
#include <stdio.h>
void lookLine (FILE * fichero)
{
char p[25];
fgets (p, sizeof (p), fichero);
printf ("%s\n", p);
}
int main (void) {
lookLine (fopen ("suma.c", "r"));
return 0;
}
And the output I get now is the correct one:
#include <stdio.h>
My reasoning is this: by using fgets I save the string of the first line of "name.c" in the p array and I return its address, which is taken by the second argument of printf function in main.
But I have found out that this only works when I use the printf function directly into the same lookLine function...
Please, could someone tell me what's really going on here?

It's because you are returning a pointer to a local array from the read function.
Remember that local variables are stored on the stack, and that includes arrays. And when the function returns that stack space is reclaimed by the compiler to be used by other function calls. So you have a pointer pointing to another function's memory.

The lifetime of the array p ends at the return statement (technically p is a local variable with automatic storage duration; this means it's lifetime ends at the matching }).
The program then invokes undefined behavior because it uses an indeterminate value (reading from a pointer that no longer points to valid memory). This is the reason you can print the string while still in read(), but get garbage when printing from main().
And note that read is a POSIX function that may be interfering with the one you defined (not a problem in a strict C89 or C99 mode, but most compilers aren't by default). [The OP in the meantime renamed the function to lookLine().]

As pointed to by Joachin Pileborg correctly, you are trying to return a stack variable which will be reclaimed, when you return from the function.
Instead you can try to pass a character array and it's size as inputs to the function read. Btw, if you don't intend to do anything else apart from calling fgets in the read function, then it is better that you call fgets in the main function itself.
Incase if you are doing some additional logic in read and you also cannot pass the buffer and it's size as input to read function, you can allocate the memory required from reading using malloc and return the pointer to the calling function. But, personally, I wouldn't recommend it as it is better to ensure the caller of the read takes the responsibility of creation and deletion of the array.

Related

Malloc array of characters dynamic vs static C

So I'm basically trying to take an input of scanf of letters (no spacing between them), place each letter into an array and spit out the corresponding letter to the array by using dynamically allocated arrays (malloc).
Crashes
#include <stdio.h>
#include <stdlib.h>
int main () {
char *userInput = malloc(sizeof(char)*3); /* dynamic */
scanf("%s", &userInput);
printf("user inputed %c", userInput[1]);
free(userInput);
return 0;
}
Runs
#include <stdio.h>
#include <stdlib.h>
int main () {
char userInput [3]; /* array */
scanf("%s", &userInput);
printf("user inputed %c", userInput[1]);
return 0;
}
Input:
asd
Output:
s
My understanding of dynamically allocated arrays was that char userInput [3]; is equivalent to char *userInput = malloc(sizeof(char)*3); but apparently from this case that isn't true? Anyone care to explain/help?
Welcome to Stack Overflow! Coincidentally, the main problem with your code is that it is vulnerable to a stack overflow. scanf has no way of knowing how big userInput is, because you didn't tell it, and will happily continue filling memory long past the end of your very short array.
If you want to capture exactly three characters (with no nul terminator), use scanf("%3c", userInput) instead. Note that without the NUL, you must not expect to treat userInput as a string; printing it via printf for example will result in a random amount of gibberish owing to the fact that C does not know where the string ended.
Now, to answer your actual question on "what's the difference between malloc and the static array": the difference is of scope. If you only ever use userInput before its creating function returns, there is no practical difference, but you're in trouble the minute you try to do something like this:
int function1 {
char my_string[3];
scanf("%3c", my_string);
return my_string; /* WRONG! DANGER! */
}
The return in the above example will happily return the pointer to my_string to the calling function. However, as soon as function1 returns, the stack is rolled back and the memory my_string occupied is essentially gone (and likely already re-used). The results are unpredictable but almost universally very bad for your program.
However, had you used malloc() instead, you could safely return the my_string pointer and the memory would persist until someone later called free(my_string) (where my_string is the pointer to the original my_string; it need not be named the same!).
This highlights another difference: with a stack variable such as char my_string[3];, you do not need to worry about (and indeed cannot) free() the memory, where as if the memory is malloc()'d instead, you must free() it if you wish to reclaim the memory.
There are some nuances to the above, such as file-scoped variables and static function variables, which I leave as topics for further reading.
As pointed in Giorgi's answer, the main problem is the incorrect usage of the address-of operator &.
However, the reason why it worked on one case and why it didn't work on another is very interesting.
char array[3]: When you declare that array, memory space will be allocated for it and array will be a label to that location(memory address). When you pass array to scanf (or use it anywhere else without subscripting []), you're passing an address to that function. Because of that, when you use the & operator on the label array, it returns the same address to you BUT with different type (T(*)[3]), which your compiler probably complained about. But, as the memory address is valid, it worked as expected.
char *array = malloc(): When you declare that variable, memory is also reserve for it, but this time in a different place and the space reserved is sizeof T(*), so it can hold a memory address. This variable also has an address in memory, which you can also get using &array. Then you malloc some memory and malloc returns to you an address of a memory block which you can now use. You can get that memory address by simply doing array. So, when you call scanf with the &array you're passing the variable address instead of the block address. That's why it crashes (I'm guessing you were not entering only two characters).
Check this code:
#include <stdio.h>
#include <stdio.h>
int main(void)
{
char *array[3];
char *ptr = malloc(3 * sizeof(char));
printf ("array : %p\n", array);
printf ("&array: %p\n\n", &array);
printf ("ptr : %p\n", ptr);
printf ("&ptr : %p\n", &ptr);
scanf("%s", &ptr);
printf ("ptr : %p\n", ptr);
return 0;
}
Which outputs:
$ ./draft
array : 0x7ffe2ad05ca0
&array: 0x7ffe2ad05ca0
ptr : 0x19a4010
&ptr : 0x7ffe2ad05c98
ABCD
ptr : 0x44434241
scanf got the address of the pointer, so when it saves the value it reads from stdin, it overwrites the address we had from malloc! The memory block we had is now gone, memory is leaking... Now, this is bad because we're overwriting stuff on our stack, memory is leaking, and it will crash.
Observe the last output: the value of ptr (which previously was the address of an allocated block) is now 0x44434241 (DCBA, ASCII Table)! How nice is that?

Issues printing whilst using getline()

I'm just having a bit of difficulty with a print. Basically, I have code and I'm assigning values to bestmatch[], which is defined as being of type line_t (see struct at bottom).
As you can see, I am storing values for bestmatch[].score (double), bestmatch[].index (int) and bestmatch[].buf (string). When I print them, show in second code block below, bestmatch[i].index and bestmatch[i].score print correctly; however, bestmatch[i].buf does not print at all.
Just to confuse matters more (for myself at least), if I print bestmatch[i].buf at the end of scorecmp (first code block), it prints fine. I've got my call to scorecmp down the very bottom for reference.
Why is it that it is printing index and score fine, but not buf? Or even more, how can I fix this behaviour?
Thank you for your help! Please let me know if you need any additional information
The print, appearing in main, is as follows (for reference, TOP_SCORING_MAX is the number of elements in bestmatch[]):
int i;
for (i = 0; i<TOP_SCORING_MAX; i++) {
if (bestmatch[i].score != -1) {
printf("line\t%d, score = %6.3f and string is %s \n",
bestmatch[i].index,bestmatch[i].score, bestmatch[i].buf);
}
}
And in case you would like the struct:
typedef struct line_t {
char* buf;
int lineLength;
int wordCount;
int index;
double score;
} line_t;
This is my call to scorecmp:
scorecmp(linePtr, bestmatch);
You need to copy the content of the strings, not just the pointers, because they seem to be destroyed, freed, or mutilated before you print them:
bestmatch[j].buf = strdup(linePtr->buf);
Don't forget to free the copied string at the end.
The getline function is the preferred method for reading lines of text from a stream.
The other standard functions, such as gets, fgets and scanf, are a little too unreliable.
The getline function reads an entire line from a stream, up to and including the next newline character.
This function takes three parameters:
A pointer to a block of memory allocated with malloc or calloc. This parameter is of type char**, and it will contain the line read by getline when the function returns.
A pointer to a variable of type size_t. This parameter specifies the size in bytes of the block of memory pointed to by the first parameter.
The stream from which to read the line.
The first parameter - a pointer to the block of memory allocated with malloc or calloc - is merely a suggestion. Function getline will automatically enlarge the block of memory as needed via realloc, so there is never a shortage of space - one reason why this function is so safe. Not only that, but it will also tell you the new size of the block, by updating the value returned in the second parameter.
That being said, every time you call function getline, you first need to:
Set maxSz to a reasonable size.
Set line.buf = malloc(maxSz).
Set the value of maxSz not too large, in order to reduce the amount of redundant memory used.
Set the value of maxSz not too small, in order to reduce the number of times getline calls realloc.

C Returning char[] Warning "returns address of local variable" [duplicate]

This question already has answers here:
Returning an address of local variable behaviour [duplicate]
(2 answers)
Closed 9 years ago.
This is a portion of a homework assignment.
I am trying to read and return a single line of a file in my method getLine.
char *getLine(FILE *input) {
char line[30];
if(fgets(line, sizeof(line), input)!=NULL)
{
return line;
}else{
return NULL;
}
}
This would seem to work from what I have been taught regarding pointers, however I am unable to remove the warning message warning: function returns address of local variable [enabled by default]. This warning is referring to the line return line;. My assignment requires that I have no warnings or errors when I compile. I don't see what I am doing wrong.
Most of the help I found suggested malloc-ing space for the line of text, but we haven't covered that in class yet even though I have done some in another class. Is that really the best way to do this? If so, would I be able to free anywhere in the program?
char line[30]; is an array with automatic storage duration. Memory where it resides is deallocated once the execution goes out of the scope of your function, thus pointer to this memory that you return becomes invalid (dangling pointer).
Trying to access memory, that has already been deallocated, results in undefined behaviour.
You can allocate your array dynamically and let the caller explicitly deallocate it:
char *getLine() {
char* line = malloc(30);
...
return line;
}
// somewhere:
char* line = getLine();
...
free(line);
Alternative without using malloc, not covered by the earlier questions as far as I could find:
/* Warning, this function is not re-entrant. It overwrites result of previous call */
char *getLine(FILE *input) {
static char line[30];
return fgets(line, sizeof(line), input);
/* fgets returns NULL on failure, line on success, no need to test it */
}
Explanation: static variables in function scope retain their values even after function returns. There's just one instance of such a variable, same one is used in every call to that function (so not re-entrant/thread-safe). Memory for static variables is allocated when program starts, it's neither heap nor stack but it's own reserved area in running program's memory space. Value of static variable is initialized just once, before it's first used (above does not have specific initialization, so it's filled with 0, but it could have an initializer too, and that would only be it's value when function is called first time).
While using static variable in this manner may seem a bit hacky (and I agree it is), it's still a valid pattern also employed by standard C for example with strtok() function. It also demonstrates the need for a version which is re-entrant, as C standard also has strtok_r(), which is more complex to use as it has one extra parameter instead of having local static variable in it.

Returning a string pointer

I started learning C, and I don't understand what I'm doing wrong. Here is a simple code of a function that returns the pid+".data".
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
char * getfilename(){
char name[60];
sprintf(name,"%i.data",getpid());
return name;
}
void main(){
char* name = getfilename();
printf("%s",name);
}
outputs: ��#�a.
So I guess that I'm doing something wrong.
char * getfilename(){
char name[60];
sprintf(name,"%i.data",getpid());
return name;
}
You cannot access name object after getfilename has returned. The lifetime of the automatic object name ends at the getfilename last }. Accessing it after the function returns is undefined behavior.
As a temporary fix you can specify name as static and it will work. But what you should do is to have the getfilename function accepts a pointer argument where the filename will be written.
EDIT:
Why I don't suggest to use strdup?
strdup is not a Standard C function. strdup lives in the POSIX world. For portability reasons whenever I can, I prefer to use Standard C functions.
strdup performs a hidden malloc call and you have not to forget to perform a free. This is contrary to all functions of the Standard C library which never call malloc (or actually that never appear to call malloc). strdup is a bad API design.
strdup is performing a copy of a string. Why do you need to perform an extra copy? Just write the string in a place you can retrieve it.
One solution is to use strdup, i.e. change:
return name;
to:
return strdup(name);
This makes a copy of your temporary (local) string using dynamic memory allocation (i.e. malloc).
You must of course make sure that you subsequently free this string when you're done with it.
You'll need:
#include <string.h> // strdup()
#include <stdlib.h> // free()
char name[60]
lives on the stack, but only as long as being inside getfilename() afterwards its freed, so any references (as also returned by getfilename()) to it become invalid.
char name[60] is a local variable which is allocated when the function is called and deallocated when it returns. When you try to return it, you're really returning it's address (after all arrays are mostly syntactic sugar for pointer arithmetic). Now, your caller has a pointer to a block of memory that has been free, and thus will likely contain garbage.
You can't return the array name from your function getfilename, because it is a (regular) local variable and those get cleaned up when the function returnes.
So, when you get back in main and try to print the returned value, the pointer name there refers to a block of memory that has been reused for other purposes.
There are several solutions for this problem:
Make name in getfilename static. This will ensure that it outlives the call to getfilename and can safely be returned, but has the drawback that all calls to getfilename use the same buffer.
Allocate the array dynamically with malloc (and don't forget to clean it up with free when you are done with it)
Pass the buffer to store the value in as a parameter.
As mentioned in the other answers you cannot return a pointer which points somewhere in the stack of a function.
You can simply pass the allocated array to getfilename() function. You can rewrite the program as follows.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void getfilename(char * name)
{
sprintf(name,"%i.data",getpid());
}
int main(void)
{
char name[60];
getfilename(name);
printf("%s\n",name);
return 0;
}
This should work fine.

Pointer and Function ambiguity in C

Please look at the following code:
char* test ( )
{
char word[20];
printf ("Type a word: ");
scanf ("%s", word);
return word;
}
void main()
{
printf("%s",test());
}
When the function returns, the variable word is destroyed and it prints some garbage value. But when I replace
char word[20];
by char *word;
it prints the correct value. According to me, the pointer variable should have been destroyed similar to the character array and the output should be some garbage value. Can anyone please explain the ambiguity?
Undefined behavior is just that - undefined. Sometimes it will appear to work, but that is just coincidence. In this case, it's possible that the uninitialized pointer just happens to point to valid writeable memory, and that memory is not used for anything else, so it successfully wrote and read the value. This is obviously not something you should count on.
You have undefined behavior either way, but purely from a "what's going on here" viewpoint, there's still some difference between the two.
When you use an array, the data it holds is allocated on the stack. When the function returns, that memory will no longer be part of the stack, and almost certainly will be overwritten in the process of calling printf.
When you use the pointer, your data is going to be written to whatever random location that pointer happens to have pointed at. Though writing there is undefined behavior, simple statistics says that if you have (for example) a 32-bit address space of ~4 billion locations, the chances of hitting one that will be overwritten in the new few instructions is fairly low.
You obviously shouldn't do either one, but the result you got isn't particularly surprising either.
Because the char array is defined and declared in the function, it is a local variable and no longer exists after the function returns. If you use a char pointer and ALLOCATE MEMORY FOR IT then it will remain, and all you need is the pointer (aka a number).
int main(int argc, char* argv[]) {
printf("%s", test());
return 0;
}
char* test(void) {
char* str = (char*)malloc(20 * sizeof(char));
scanf("%19s", str);
return str;
}
Notice how I used %19s instead of %s. Your current function can easily lead to a buffer overflow if a user enters 20 or more characters.
During program execution first it will create activation records for the function main in stack segment of the process memory. In that main activation records it will allocate memory for the local variable of that function(main) and some more memory for internal purpose. In your program main doesn't has any local variable, so it will not allocate any memory for local variables in main activation records.
Then while executing the statement for calling the function test, it will create one more activation records for the calling function(test) and it will allocate 20 bytes for the local variable word.
Once the control exits the function test, activation record created for that function will be poped out of that stack. Then it will continue to execute the remaining statment (printf) of the called function main. Here printf is trying to print the characters in the test function's local variable which is already poped out of the stack. So this behaviour is undefined, sometimes it may print the proper string or else it will print some junk strings.
So in this situation only dynamic memory comes into picture. With the help of dynamic memory we can control the lifetime(or scope) of a variable. So use dynamic memory like below.
char *word = NULL:
word = (char *) malloc(sizeof(char) * 20);
Note : Take care of NULL check for the malloc return value and also dont forget to free the allocated memory after printf in main function.

Resources