I've been learning C for like 5 days, and so I tried doing some little projects. I created a very simple library that automates getting a string from the user,then implemented it in a program which just outputs the string's value.
It runs perfectly on Windows (Compiled through MSVC: 'cl .\main.c /link .\get_string\m_string.obj') but it doesn't in Linux (Compiled with gcc using : 'gcc -o test main.c m_string.o')
I know that MAX being 1024 makes absolutely no sense, it's just a test value.
//main.c
#include <stdio.h>
#include "get_string/m_string.h"
int main(int argc, char *argv[])
{
char *inputf = get_string("Something: ");
printf("%s", inputf);
return 0;
}
// m_string.h
#include <stdio.h>
#define MAX 1024
char *get_string(char *prompt);
//m_string.c
#include "m_string.h"
char *get_string(char *prompt)
{
char *s[MAX];
printf("%s", prompt);
fgets(s, MAX, stdin);
return s;
}
Running main.c on Windows works as expected:
Something: something
something
Running main.c on Linux:
Something: something
(null)$
Since I am using a very big value for the maximum memory used in fgets(), I don't think that a buffer overflow is the cause (Would have probably gotten Segmentation Fault otherwise).
Thank you for reading and I hope someone can shed some light on the matter for an absolute beginer like me.
CodePudding user response:
char *s[MAX];
creates an array ofMAX
pointers, notchar
values.ALWAYS enable your compiler's warnings. It would have found this. With gcc, I use
-Wall -Wextra -pedantic
.get_string
returns a pointer to a variable that no longer exists onceget_string
returns.One way to solve this is to allocate a buffer using
malloc
, andfree
that buffer in the caller.
#include <stdio.h>
#include <stdlib.h>
#define MAX 1024
char *get_string( const char *prompt ) {
char *s = malloc( MAX );
if ( !s )
return NULL;
printf( "%s", prompt );
if ( !fgets( s, MAX, stdin ) ) {
free( s );
return NULL;
}
return s;
}
int main( void ) {
char *inputf = get_string( "Something: " );
if ( !inputf ) {
perror( NULL );
exit( 1 );
}
printf( "%s", inputf );
free( inputf );
return 0;
}
Demo on Compiler Explorer
CodePudding user response:
It really does not run "correctly", because this is undefined behavior. You may not access temporary storage outside of the scope in which it was defined.
In addition to this, you also have a type error: char *s[MAX];
defines an array of MAX
char pointers. Using this as a string buffer should not have been allowed past the compiler.
If you do not want to allocate memory dynamically for this, then make the string buffer static. You can even make it thread-local (since C11) if for some reason you plan to use this function in concurrent environments.
#include <stdio.h>
#define MAX 1024
char *get_string(const char *prompt)
{
static _Thread_local char s[MAX];
printf("%s", prompt);
if (!fgets(s, MAX, stdin)) {
s[0] = '\0';
}
return s;
}
int main(int argc, char *argv[])
{
char *inputf = get_string("Something: ");
printf("%s", inputf);
return 0;
}