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("%s\n", 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");
if( *filehdl ) invokes undefined behavior since you are accessing a non-initialized FILE 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 the if 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:
#include <stdio.h>
int main() {
int* pointer[20];
for(int i = 0; i < 20; ++i) {
printf("%p\n", &pointer[i]);
}
}
Output:
(nil)
(nil)
(nil)
(nil)
(nil)
(nil)
(nil)
(nil)
(nil)
0x1007
0x5631f0cff040
0xd
0x7ffe17efbbf0
0x7ffe17efc019
0x7f512adab5e0
0x5631f0d0023d
0x7f512ad862e8
0x5631f0d001f0
(nil)
0x5631f0d00080
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:
FILE *filePtr = NULL;
Related
I am write a simple MPI program, I am confused at the output when we call MPI_Abort.
The code is
// main.cpp
#include "mpi.h"
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv)
{
MPI_Init(&argc, &argv);
int x = 1;
if (x == 1)
{
MPI_Abort(MPI_COMM_WORLD, -100);
}
MPI_Finalize();
return 0;
}
I am using the follow command to compile the program.
mpic++ main.cpp
The operating system is Ubuntu 18.04
The compiler is MPICH, type mpic++ -v in terminal can obtain detailed information of compiler:
mpicxx for MPICH version 3.3a2
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 7.4.0-1ubuntu1~18.04.1' --with-bugurl=file:///usr/share/doc/gcc-7/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-7 --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 --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib --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 --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1)
If I run the executable file by the follow command
./a.out
The output is
application called MPI_Abort(MPI_COMM_WORLD, -100) - process 0
[unset]: write_line error; fd=-1 buf=:cmd=abort exitcode=-100
:
system msg for write_line failure : Bad file descriptor
How to understand the write line error? write line failure? Indeed what happens?
If I run the executable file by the follow command
mpirun -np 2 ./a.out
The output is
application called MPI_Abort(MPI_COMM_WORLD, -100) - process 0
[cli_0]: readline failed
How to understand the read line failed? Indeed what happens?
Thanks for your time.
I just installed a vanilla CentOS 6 and when I try to get large file support using the -D_FILE_OFFSET_BITS=64 the field st_size is still only 32 bits
uname -a:
Linux vm01 2.6.32-504.el6.x86_64 #1 SMP Wed Oct 15 04:27:16 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
What I can see this host is 64 bits.
My simple test program to see if st_size accept value larger than 32 bits:
#include <sys/stat.h>
int main(int argc, char *argv[]) {
struct stat s;
s.st_size = 1024*1024*1024*1024; // 1 Tbyte
return 0;
}
Compile command:
gcc -c test.c -D_FILE_OFFSET_BITS=64 -o test
Result:
test.c: In function ‘main’:
test.c:7: warning: left shift count >= width of type
I don't understand why gcc complains as according to all doc I've read the stat should support large file such as 64 bits for the st_size.
gcc -v
Using built-in specs.
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.4.7 20120313 (Red Hat 4.4.7-11) (GCC)
Can someone help me solve this mystery?
Thanks
If you want to use a big number then you need to tell the compiler that you want to use a big number.
s.st_size = 1024ULL * 1024 * 1024 * 1024;
The following code produces "Quit (core dumped)" when I run it and type control \. I don't even get to hit return. I got this code from a tutorial book.
I tried debugging with gcc but it does this: (At the blank line it's running getline and I'm typing control \.)
14 bytes_read = getline (&my_string, &nbytes, stdin); (gdb)
Program received signal SIGQUIT, Quit. 0x004011e5 in main () at
myfile.c:14 14 bytes_read = getline (&my_string, &nbytes,
stdin); (gdb)
...when I single step it.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int bytes_read;
int nbytes = 100;
char *my_string;
puts ("Please enter a line of text.");
/* These 2 lines are the heart of the program. */
my_string = (char *) malloc (nbytes + 1);
bytes_read = getline (&my_string, &nbytes, stdin);
if (bytes_read == -1)
{
puts ("ERROR!");
}
else
{
puts ("You typed:");
puts (my_string);
}
return 0;
}
I used command-line "gcc -g myfile.c".
I am on Cygwwin bash
$ uname --all CYGWIN_NT-5.1 LENOVO-3AA1E185 1.7.29(0.272/5/3)
2014-04-07 13:44 i686 Cygwin
$ gcc -v Using built-in specs. COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-pc-cygwin/4.8.2/lto-wrapper.exe
Target: i686-pc-cygwin Configured with:
/cygdrive/i/szsz/tmpp/gcc4/gcc-4.8.2-2/src/gcc-4.8.2/configure
--srcdir=/cygdrive/i/szsz/tmpp/gcc4/gcc-4.8.2-2/src/gcc-4.8.2 --prefix=/usr --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin --libexecdir=/usr/libexec --datadir=/usr/share --localstatedir=/var --sysconfdir=/etc --libdir=/usr/lib --datarootdir=/usr/share --docdir=/usr/share/doc/gcc --htmldir=/usr/share/doc/gcc/html -C --build=i686-pc-cygwin --host=i686-pc-cygwin --target=i686-pc-cygwin --without-libiconv-prefix --without-libintl-prefix --enable-shared --enable-shared-libgcc --enable-static --enable-version-specific-runtime-libs --enable-bootstrap --disable-__cxa_atexit --with-dwarf2 --with-arch=i686 --with-tune=generic --disable-sjlj-exceptions --enable-languages=ada,c,c++,fortran,java,lto,objc,obj-c++ --enable-graphite --enable-threads=posix --enable-libatomic --enable-libgomp --disable-libitm --enable-libquadmath --enable-libquadmath-support --enable-libssp --enable-libada --enable-libjava --enable-libgcj-sublibs --disable-java-awt --disable-symvers --with-ecj-jar=/usr/share/java/ecj.jar --with-gnu-ld --with-gnu-as --with-cloog-include=/usr/include/cloog-isl --without-libiconv-prefix --without-libintl-prefix --with-system-zlib --libexecdir=/usr/lib Thread model: posix gcc version 4.8.2 (GCC)
underneath cygwin is Microsoft Windows XP Professional 32-bit SP3
Control-C is a Quit Signal trigger on most systems :
The SIGQUIT signal is similar to SIGINT, except that it's controlled
by a different key—the QUIT character, usually C-\—and produces a core
dump when it terminates the process, just like a program error signal.
You can think of this as a program error condition “detected” by the
user.
quoted from GNU. So this behavior is expected: You program did receive the SIGQUIT signal
I am new to C and have a question. I think I made a mistake, but the compiler is not giving a warning and the program runs fine.
I believe there is an error in line 4:
#include <stdio.h>
void void_int(int x);
void void_int(x) { // <-- no type definition for parameter x
printf( "void_int: %d\n", x);
}
int main(int argc, char **argv) {
printf("Hello world\n");
// declare a function pointer
void (*by_ref_void_int)(int);
// assign pointer to a function
by_ref_void_int = &void_int;
// run referenced function
by_ref_void_int(2);
return 0;
}
I do not define a type for the first argument to the function definition void void_int(x) {, however, gcc is not giving me any errors. The program runs just fine.
I compile with: gcc -Wall -o fp fp.c.
Would anybody help me trying to understand? Is there a default type for function arguments and is it possibly int?
Thanks and best wishes
-S
$ gcc -v
Using built-in specs.
COLLECT_GCC=/usr/bin/gcc-4.7.real
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.7/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 4.7.2-5' --with-bugurl=file:///usr/share/doc/gcc-4.7/README.Bugs --enable-languages=c,c++,go,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.7 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.7 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --enable-objc-gc --with-arch-32=i586 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.7.2 (Debian 4.7.2-5)
to keep the compatibility with arcaic versions of the C language, if a declaration specifies no type, the default type is assumed to be int.
If you simply specify a version of the language, the compiler will surely help you spotting this
gcc -std=c99 a.c
a.c: In function ‘void_int’:
a.c:4:6: warning: type of ‘x’ defaults to ‘int’ [enabled by default]
void void_int(x) { // <-- no type definition for parameter x
^
try to specify a version of the language, it's always a good habit that will help you.
I have the following code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char buf[256];
printf("\nString - Enter your string: ");
scanf ("%s", buf);
char *_S = buf;
.....
}
defining char *_S = buf; in the middle of the code could generate compilation error in some CXX versions
What version of CXX this could generate error. and are there some option to add to the gcc command in order to avoid this error?
EDIT:
I tried with the following option and I did not get any error:
$ gcc -std=c99 -o test test.c
$ gcc -std=c90 -o test test.c
$ gcc -std=c89 -o test test.c
$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/i386-linux-gnu/gcc/i686-linux-gnu/4.5.2/lto-wrapper
Target: i686-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.5.2-8ubuntu4' --with-bugurl=file:///usr/share/doc/gcc-4.5/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.5 --enable-shared --enable-multiarch --with-multiarch-defaults=i386-linux-gnu --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib/i386-linux-gnu --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.5 --libdir=/usr/lib/i386-linux-gnu --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-plugin --enable-gold --enable-ld=default --with-plugin-ld=ld.gold --enable-objc-gc --enable-targets=all --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=i686-linux-gnu --host=i686-linux-gnu --target=i686-linux-gnu
Thread model: posix
gcc version 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4)
$
You need to tell GCC to build as C90 or earlier.
$ gcc -std=c90 mycode.c
To avoid the error, compile as -std=c99 or -std=c11.
By default, GCC uses "non-standard GNU goo", which typically will default to something similar to C99 in any GCC version released during the past 10 years or so. Meaning that by default, GCC shouldn't give you an error.
C99 is the first version of the standard that allows local variables to be declared after the first non-declaring statement of a block.
So if you pass -std=c99 to gcc, it will accept your code. Obviously, later versions of the standard also allow locals to be declared after non-declaring statements.
Prior to C99 local variable declarations must be declared at the top of a block. If your compiler does not support C99 you can either simply use C++ compilation, or create an unconditional statement block
int main()
{
char buf[256];
printf("\nString - Enter your string: ");
scanf ("%s", buf);
// Unconditional block to localise the variable buf
{
char *_S = buf;
...
}
// buf no longer in scope here
...
}