Initializing the file name via pointer let’s crash the gcc on Linux but not on MacOS, can someone explain this?
#include <stdio.h>
int doOpenFile( char *name, FILE **filehdl, char *option );
int doOpenFile( char *name, FILE **filehdl, char *option )
{
if( *filehdl ) fclose( *filehdl );
if( (*filehdl = fopen( name, option )) == NULL ) return( -1 );
return( 0 );
}
int main(int argc, char **argv)
{
char *file = "test.c";
FILE *filePtr;
doOpenFile(file, &filePtr, "r");
if(filePtr != NULL) fclose(filePtr);
printf("%sn", file);
}
Linux gcc:
oot@1fa88ab5df9e:/build/open62541-server# gcc -o test test.c
root@1fa88ab5df9e:/build/open62541-server# ./test
Segmentation fault (core dumped)
root@1fa88ab5df9e:/build/open62541-server# gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 10.2.1 20210110 (Debian 10.2.1-6)
root@1fa88ab5df9e:/build/open62541-server#
MacOS:
open62541-server % gcc test.c -o test
open62541-server % ./test
test.c
open62541-server % gcc -v
Apple clang version 14.0.0 (clang-1400.0.29.102)
Target: arm64-apple-darwin21.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
open62541-server %
Weird because even if I don’t pass the variable, the gcc on Linux crash
doOpenFile("test.c", &filePtr, "r");
2
Answers
if( *filehdl )
invokes undefined behavior since you are accessing a non-initializedFILE
pointer. Either document to the caller that the function assumes the parameter to either be a null pointer or a valid file pointer, or drop theif
statement.Unrelated to your problem, you should also use
const char*
everywhere in this code, for const correctness and because string literals are read-only anyway.Like the others said. When you declare a variable in C it does contain a (seemingly) random value that happened to be in RAM at runtime. That value can be NULL (or nil if you print it on the console, those two words mean the same). I wrote a small program to show this:
Output:
So you see that there is a chance that the value is NULL, and that’s probably what happened in you MacOS try. But feel free to run my small program here to check if that is always the case on your Mac.
When you pass a pointer that is not NULL to
fclose( *filehdl );
you get a segmentation fault because it points to an address that does not belong to your program.The easiest way to fix your problem ist to just initialize: