use gcc compile a project that shows "undefined reference to `abort'" - c
I wrote a printf myselef that use va_list/va_arg/va_start/va_end/va_arg.
typedef char *va_list;
#define _AUPBND (sizeof (acpi_native_int) - 1)
#define _ADNBND (sizeof (acpi_native_int) - 1)
#define _bnd(X, bnd) (((sizeof (X)) + (bnd)) & (~(bnd)))
#define va_arg(ap, T) (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND))))
#define va_end(ap) (void) 0
#define va_start(ap, A) (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND))))
At first,I copy these macros from linux kernel and the printf can print 32-bit integer correct but cannot print 64-bit integer and print double/float may fail or collapse.Then I check the code and I guess the va_* may have errors,so I use __builtin_va_* instead of kernel's va_*.
typedef __builtin_va_list va_list;
#define va_start(v,l) __builtin_va_start(v,l)
#define va_end(v) __builtin_va_end(v)
#define va_arg(v,l) __builtin_va_arg(v,l)
But gcc prompt "undefined reference to `abort'",so I write a empty abort() and myprintf works corretly.
My questions are:
Why linux kernel's va_list/va_arg/va_start/va_end/va_arg can not used for printf 64-bit integer and double/float?
When I used __builtin_va_start/__builtin_va_arg/__builtin_va_end/__builtin_va_list, why gcc prompt "undefined reference to abort'"? But I can not find the definition of__builtin_va_*`, where're their definition?
Don't cut and paste things from the Linux headers. Instead, put this at the top of your source file:
#include <stdarg.h>
This will give you everything you need in order to use va_list and va_arg. However, it won't pull in printf or any of the standard I/O stuff (which lives in <stdio.h>).
gcc's __builtin_va_arg() apparently will call abort() (at least on some platforms or situations) if it's invoked with a type argument cannot have been passed in the ... part of the argument list for a function call.
For example, due to promotions a char or float passed as such an argument will have been promoted to int or double. Accessing those arguments as va_arg(ap,char) or va_arg(ap,float) is undefined behavior and gcc may call abort() in that situation - or it may do something else (my MinGW compiler will execute an invalid instruction to cause a crash).
You might see something like this when compiled:
In file included from D:\temp\test.c:2:0:
D:\temp\test.c: In function 'foo':
D:\temp\test.c:12:16: warning: 'char' is promoted to 'int' when passed through '...' [enabled by default]
c = va_arg(ap,char);
^
D:\temp\test.c:12:16: note: (so you should pass 'int' not 'char' to 'va_arg')
D:\temp\test.c:12:16: note: if this code is reached, the program will abort
The 'definition' of __builtin_va_* is compiled into the compiler (that's why 'builtin' is part of the name).
As far as the Linux macros for varargs access: while the definitions you took from a linux kernel header do exist in include/acpi/platform/acenv.h, if you look carefully at the conditional compilation in effect, you'll see that those macros aren't used when building the linux kernel. I'm not exactly sure when those macros are in effect, but they won't work with x64/x86-64/amd64 builds because the ABI on that platform isn't entirely stack-based. See section 3.5.6 of the "System V Application Binary Interface - AMD64 Architecture Processor Supplement" for details.
Related
Figure out function parameter count at compile time
I have a C library (with C headers) which exists in two different versions. One of them has a function that looks like this: int test(char * a, char * b, char * c, bool d, int e); And the other version looks like this: int test(char * a, char * b, char * c, bool d) (for which e is not given as function parameter but it's hard-coded in the function itself). The library or its headers do not define / include any way to check for the library version so I can't just use an #if or #ifdef to check for a version number. Is there any way I can write a C program that can be compiled with both versions of this library, depending on which one is installed when the program is compiled? That way contributors that want to compile my program are free to use either version of the library and the tool would be able to be compiled with either. So, to clarify, I'm looking for something like this (or similar): #if HAS_ARGUMENT_COUNT(test, 5) test("a", "b", "c", true, 20); #elif HAS_ARGUMENT_COUNT(test, 4) test("a", "b", "c", true); #else #error "wrong argument count" #endif Is there any way to do that in C? I was unable to figure out a way. The library would be libogc ( https://github.com/devkitPro/libogc ) which changed its definition of if_config a while ago, and I'd like to make my program work with both the old and the new version. I was unable to find any version identifier in the library. At the moment I'm using a modified version of GCC 8.3.
This should be done at the configure stage, using an Autoconf (or CMake, or whatever) test step -- basically, attempting to compile a small program which uses the five-parameter signature, and seeing if it compiles successfully -- to determine which version of the library is in use. That can be used to set a preprocessor macro which you can use in an #if block in your code.
I think there's no way to do this at the preprocesing stage (at least not without some external scripts). On the other hand, there is a way to detect a function's signature at compiling time if you're using C11: _Generic. But remember: you can't use this in a macro like #if because primary expressions aren't evaluated at the preprocessing stage, so you can't dynamically choose to call the function with signature 1 or 2 in that stage. #define WEIRD_LIB_FUNC_TYPE(T) _Generic(&(T), \ int (*)(char *, char *, char *, bool, int): 1, \ int (*)(char *, char *, char *, bool): 2, \ default: 0) printf("test's signature: %d\n", WEIRD_LIB_FUNC_TYPE(test)); // will print 1 if 'test' expects the extra argument, or 2 otherwise I'm sorry if this does not answer your question. If you really can't detect the version from the "stock" library header file, there are workarounds where you can #ifdef something that's only present in a specific version of that library. This is just a horrible library design. Update: after reading the comments, I should clarify for future readers that it isn't possible in the preprocessing stage but it is possible at compile time still. You'd just have to conditionally cast the function call based on my snippet above. typedef int (*TYPE_A)(char *, char *, char *, bool, int); typedef int (*TYPE_B)(char *, char *, char *, bool); int newtest(char *a, char *b, char *c, bool d, int e) { void (*func)(void) = (void (*)(void))&test; if (_Generic(&test, TYPE_A: 1, TYPE_B: 2, default: 0) == 1) { return ((TYPE_A)func)(a, b, c, d, e); } return ((TYPE_B)func)(a, b, c, d); } This indeed works although it might be controversial to cast a function this way. The upside is, as #pizzapants184 said, the condition will be optimized away because the _Generic call will be evaluated at compile-time.
I don't see any way to do that with standard C, if you are compiling with gcc a very very ugly way can be using gcc aux-info in a command and passing the number of parameters with -D: #!/bin/sh gcc -aux-info output.info demo.c COUNT=`grep "extern int foo" output.info | tr -dc "," | wc -m` rm output.info gcc -o demo demo.c -DCOUNT="$COUNT + 1" ./demo This snippet #include <stdio.h> int foo(int a, int b, int c); #ifndef COUNT #define COUNT 0 #endif int main(void) { printf("foo has %d parameters\n", COUNT); return 0; } outputs foo has 3 parameters
Attempting to support compiling code with multiple versions of a static library serves no useful purpose. Update your code to use the latest release and stop making life more difficult than it needs to be.
In Dennis Ritchie's original C language, a function could be passed any number of arguments, regardless of the number of parameters it expected, provided that the function didn't access any parameters beyond those that were passed to it. Even on platforms whose normal calling convention wouldn't be able to accommodate this flexibility, C compilers would generally used a different calling convention that could support it unless functions were marked with qualifiers like pascal to indicate that they should use the ordinary calling convention. Thus, something like the following would have had fully defined behavior in Ritchie's original C language: int addTwoOrThree(count, x, y, z) int count, x, y, z; { if (count == 3) return x+y+z; else return x+y; } int test() { return count(2, 10,20) + count(3, 1,2,3); } Because there are some platforms where it would be impractical to support such flexibility by default, the C Standard does not require that compilers meaningfully process any calls to functions which have more or fewer arguments than expected, except that functions which have been declared with a ... parameter will "expect" any number of arguments that is at least as large as the number of actual specified parameters. It is thus rare for code to be written that would exploit the flexibility that was present in Ritchie's language. Nonetheless, many implementations will still accept code written to support that pattern if the function being called is in a separate compilation unit from the callers, and it is declared but not prototyped within the compilation units that call it.
you don't. the tools you're working with are statically linked and don't support versioning. you can get around it using all kind of tricks and tips that have been mentioned, but at the end of the day they are ugly patch works of something you're trying to do that makes no sense in this context(toolkit/code environment). you design your code for the version of the toolkit you have installed. its a hard requirement. i also don't understand why you would want to design your gamecube/wii code to allow building on different versions. the toolkit is constantly changing to fix bugs, assumptions etc etc. if you want your code to use an old version that potentially have bugs or do things wrong, that is on you. i think you should realize what kind of botch work you're dealing with here if you need or want to do this with an constantly evolving toolkit.. I also think, but this is because i know you and your relationship with DevKitPro, i assume you ask this because you have an older version installed and your CI builds won't work because they use a newer version (from docker). its either this, or you have multiple versions installed on your machine for a different project you build (but won't update source for some odd reason).
If your compiler is a recent GCC, e.g. some GCC 10 in November 2020, you might write your own GCC plugin to check the signature in your header files (and emit appropriate and related C preprocessor #define-s and/or #ifdef, à la GNU autoconf). Your plugin could (for example) fill some sqlite database and you would later generate some #include-d header file. You then would set up your build automation (e.g. your Makefile) to use that GCC plugin and the data it has computed when needed. For a single function, such an approach is overkill. For some large project, it could make sense, in particular if you also decide to also code some project-specific coding rules validator in your GCC plugin. Writing a GCC plugin could take weeks of your time, and you may need to patch your plugin source code when you would switch to a future GCC 11. See also this draft report and the European CHARIOT and DECODER projects (funding the work described in that report). BTW, you might ask the authors of that library to add some versioning metadata. Inspiration might come from libonion or Glib or libgccjit. BTW, as rightly commented in this issue, you should not use an unmaintained old version of some opensource library. Use the one that is worked on. I'd like to make my program work with both the old and the new version. Why? making your program work with the old (unmaintained) version of libogc is adding burden to both you and them. I don't understand why you would depend upon some old unmaintained library, if you can avoid doing that. PS. You could of course write a plugin for GCC 8. I do recommend switching to GCC 10: it did improve.
I'm not sure this solves your specific problem, or helps you at all, but here's a preprocessor contraption, due to Laurent Deniau, that counts the number of arguments passed to a function at compile time. Meaning, something like args_count(a,b,c) evaluates (at compile time) to the constant literal constant 3, and something like args_count(__VA_ARGS__) (within a variadic macro) evaluates (at compile time) to the number of arguments passed to the macro. This allows you, for instance, to call variadic functions without specifying the number of arguments, because the preprocessor does it for you. So, if you have a variadic function void function_backend(int N, ...){ // do stuff } where you (typically) HAVE to pass the number of arguments N, you can automate that process by writing a "frontend" variadic macro #define function_frontend(...) function_backend(args_count(__VA_ARGS__), __VA_ARGS__) And now you call function_frontend() with as many arguments as you want: I made you Youtube tutorial about this. #include <stdint.h> #include <stdarg.h> #include <stdio.h> #define m_args_idim__get_arg100( \ arg00,arg01,arg02,arg03,arg04,arg05,arg06,arg07,arg08,arg09,arg0a,arg0b,arg0c,arg0d,arg0e,arg0f, \ arg10,arg11,arg12,arg13,arg14,arg15,arg16,arg17,arg18,arg19,arg1a,arg1b,arg1c,arg1d,arg1e,arg1f, \ arg20,arg21,arg22,arg23,arg24,arg25,arg26,arg27,arg28,arg29,arg2a,arg2b,arg2c,arg2d,arg2e,arg2f, \ arg30,arg31,arg32,arg33,arg34,arg35,arg36,arg37,arg38,arg39,arg3a,arg3b,arg3c,arg3d,arg3e,arg3f, \ arg40,arg41,arg42,arg43,arg44,arg45,arg46,arg47,arg48,arg49,arg4a,arg4b,arg4c,arg4d,arg4e,arg4f, \ arg50,arg51,arg52,arg53,arg54,arg55,arg56,arg57,arg58,arg59,arg5a,arg5b,arg5c,arg5d,arg5e,arg5f, \ arg60,arg61,arg62,arg63,arg64,arg65,arg66,arg67,arg68,arg69,arg6a,arg6b,arg6c,arg6d,arg6e,arg6f, \ arg70,arg71,arg72,arg73,arg74,arg75,arg76,arg77,arg78,arg79,arg7a,arg7b,arg7c,arg7d,arg7e,arg7f, \ arg80,arg81,arg82,arg83,arg84,arg85,arg86,arg87,arg88,arg89,arg8a,arg8b,arg8c,arg8d,arg8e,arg8f, \ arg90,arg91,arg92,arg93,arg94,arg95,arg96,arg97,arg98,arg99,arg9a,arg9b,arg9c,arg9d,arg9e,arg9f, \ arga0,arga1,arga2,arga3,arga4,arga5,arga6,arga7,arga8,arga9,argaa,argab,argac,argad,argae,argaf, \ argb0,argb1,argb2,argb3,argb4,argb5,argb6,argb7,argb8,argb9,argba,argbb,argbc,argbd,argbe,argbf, \ argc0,argc1,argc2,argc3,argc4,argc5,argc6,argc7,argc8,argc9,argca,argcb,argcc,argcd,argce,argcf, \ argd0,argd1,argd2,argd3,argd4,argd5,argd6,argd7,argd8,argd9,argda,argdb,argdc,argdd,argde,argdf, \ arge0,arge1,arge2,arge3,arge4,arge5,arge6,arge7,arge8,arge9,argea,argeb,argec,arged,argee,argef, \ argf0,argf1,argf2,argf3,argf4,argf5,argf6,argf7,argf8,argf9,argfa,argfb,argfc,argfd,argfe,argff, \ arg100, ...) arg100 #define m_args_idim(...) m_args_idim__get_arg100(, ##__VA_ARGS__, \ 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0, \ 0xef,0xee,0xed,0xec,0xeb,0xea,0xe9,0xe8,0xe7,0xe6,0xe5,0xe4,0xe3,0xe2,0xe1,0xe0, \ 0xdf,0xde,0xdd,0xdc,0xdb,0xda,0xd9,0xd8,0xd7,0xd6,0xd5,0xd4,0xd3,0xd2,0xd1,0xd0, \ 0xcf,0xce,0xcd,0xcc,0xcb,0xca,0xc9,0xc8,0xc7,0xc6,0xc5,0xc4,0xc3,0xc2,0xc1,0xc0, \ 0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0, \ 0xaf,0xae,0xad,0xac,0xab,0xaa,0xa9,0xa8,0xa7,0xa6,0xa5,0xa4,0xa3,0xa2,0xa1,0xa0, \ 0x9f,0x9e,0x9d,0x9c,0x9b,0x9a,0x99,0x98,0x97,0x96,0x95,0x94,0x93,0x92,0x91,0x90, \ 0x8f,0x8e,0x8d,0x8c,0x8b,0x8a,0x89,0x88,0x87,0x86,0x85,0x84,0x83,0x82,0x81,0x80, \ 0x7f,0x7e,0x7d,0x7c,0x7b,0x7a,0x79,0x78,0x77,0x76,0x75,0x74,0x73,0x72,0x71,0x70, \ 0x6f,0x6e,0x6d,0x6c,0x6b,0x6a,0x69,0x68,0x67,0x66,0x65,0x64,0x63,0x62,0x61,0x60, \ 0x5f,0x5e,0x5d,0x5c,0x5b,0x5a,0x59,0x58,0x57,0x56,0x55,0x54,0x53,0x52,0x51,0x50, \ 0x4f,0x4e,0x4d,0x4c,0x4b,0x4a,0x49,0x48,0x47,0x46,0x45,0x44,0x43,0x42,0x41,0x40, \ 0x3f,0x3e,0x3d,0x3c,0x3b,0x3a,0x39,0x38,0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30, \ 0x2f,0x2e,0x2d,0x2c,0x2b,0x2a,0x29,0x28,0x27,0x26,0x25,0x24,0x23,0x22,0x21,0x20, \ 0x1f,0x1e,0x1d,0x1c,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13,0x12,0x11,0x10, \ 0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00, \ ) typedef struct{ int32_t x0,x1; }ivec2; int32_t max0__ivec2(int32_t nelems, ...){ // The largest component 0 in a list of 2D integer vectors int32_t max = ~(1ll<<31) + 1; // Assuming two's complement va_list args; va_start(args, nelems); for(int i=0; i<nelems; ++i){ ivec2 a = va_arg(args, ivec2); max = max > a.x0 ? max : a.x0; } va_end(args); return max; } #define max0_ivec2(...) max0__ivec2(m_args_idim(__VA_ARGS__), __VA_ARGS__) int main(){ int32_t max = max0_ivec2(((ivec2){0,1}), ((ivec2){2,3}, ((ivec2){4,5}), ((ivec2){6,7}))); printf("%d\n", max); }
What implementation of getenv is used if no header is included?
I am working on a simple program for learning purposes and I see the following behavior: If I attempt to read an environment variable using getenv it works as expected: #include <stdio.h> #include <stdlib.h> int main() { printf("PATH is %s", getenv("PATH")); return 0; } If I do not include stdlib.h, I get the expected warning: env.c:7:26: warning: implicit declaration of function ‘getenv’; did you mean ‘getline’? [-Wimplicit-function-declaration] The program still compiles. Running the program with the header runs as expected, the program without the header included gets a seg fault. If I inspect the disassembly of both programs, I see that there is a call to getenv#PLT call getenv#PLT When I output the disassembly of the 2 programs (where the only difference in the c source code is the header include), the only difference I see is that when we include the header there's an instruction to set %eax to 0 before calling getenv. movl $0, %eax If I step through in gdb for the program without included header, it does jump into getenv and does run a whole lot of code within the c runtime. I am wondering what is the exact reason why not including the header here causes this kind of behavior? Why does c let this compile? Some info: gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1) I am compiling like this: gcc -O0 -S env.c
In C language, if you forget to include the header file, the getenv() function is interpreted as int getenv(...). If you include the header file, the getenv() function is interpreted as char* getenv(const char*). Because of implementation of printf() the only difference in your case is the size of the return value. If sizeof(int) == sizeof(char*), then you have no problem (this happens for 32-bit programs). If sizeof(int) != sizeof(char*), you get an error (this happens for 64-bit programs). This is explained in the comment #5
Defining macro to change print function error due to argument difference
I'm trying to use unity testing framework with an NRF51822 board, but in order to see the output from unity i need to reroute it / pipe so its visible on my coumputer. I am using SEGGER RTT to print in my porject and ideally id use the same for unity.c output. According to unity By default, Unity prints its results to stdout as it runs. This works perfectly fine in most situations where you are using a native compiler for testing. It works on some simulators as well so long as they have stdout routed back to the command line. There are times, however, where the simulator will lack support for dumping results or you will want to route results elsewhere for other reasons. In these cases, you should define the UNITY_OUTPUT_CHAR macro. This macro accepts a single character at a time (as an int, since this is the parameter type of the standard C putchar function most commonly used). You may replace this with whatever function call you like. * Output* - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if desired /*------------------------------------------------------- * Output Method: stdout (DEFAULT) *-------------------------------------------------------*/ #ifndef UNITY_OUTPUT_CHAR /* Default to using putchar, which is defined in stdio.h */ #include <stdio.h> #define UNITY_OUTPUT_CHAR(a) (void)putchar(a) #else /* If defined as something else, make sure we declare it here so it's ready for use */ #ifndef UNITY_OMIT_OUTPUT_CHAR_HEADER_DECLARATION extern void UNITY_OUTPUT_CHAR(int); #endif #endif I tried to define #define UNITY_OUTPUT_CHAR(a) SEGGER_RTT_WriteString(0, a) However i get the following > $ make rm -rf _build echo Makefile Makefile mkdir _build Compiling > file: system_nrf51.c Compiling file: main.c > C:/NXTSNS/nRF5_SDK_11.0.0_89a8197/examples/peripheral/blinky/main.c:31:53: > error: expected declaration specifiers or '...' before numeric > constant > #define UNITY_OUTPUT_CHAR(a) SEGGER_RTT_WriteString(0, a) > ^ C:/NXTSNS/Unittesting/unity/src/unity_internals.h:250:13: note: in > expansion of macro 'UNITY_OUTPUT_CHAR' extern void > UNITY_OUTPUT_CHAR(int); > ^ Makefile:150: recipe for target '_build/main.o' failed make: *** [_build/main.o] Error 1 I also tried this alternative of calling segger in a function and casting to char * as follows void print_test(int a){ SEGGER_RTT_WriteString(0, (char *) a); } but unfortuneatly i dont see any output when i call print_test How should i define the macro such that i can send the output to segger or if there is a more suitable alternative what is it?
How to force a crash in C, is dereferencing a null pointer a (fairly) portable way?
I'm writing my own test-runner for my current project. One feature (that's probably quite common with test-runners) is that every testcase is executed in a child process, so the test-runner can properly detect and report a crashing testcase. I want to also test the test-runner itself, therefore one testcase has to force a crash. I know "crashing" is not covered by the C standard and just might happen as a result of undefined behavior. So this question is more about the behavior of real-world implementations. My first attempt was to just dereference a null-pointer: int c = *((int *)0); This worked in a debug build on GNU/Linux and Windows, but failed to crash in a release build because the unused variable c was optimized out, so I added printf("%d", c); // to prevent optimizing away the crash and thought I was settled. However, trying my code with clang instead of gcc revealed a surprise during compilation: [CC] obj/x86_64-pc-linux-gnu/release/src/test/test/test_s.o src/test/test/test.c:34:13: warning: indirection of non-volatile null pointer will be deleted, not trap [-Wnull-dereference] int c = *((int *)0); ^~~~~~~~~~~ src/test/test/test.c:34:13: note: consider using __builtin_trap() or qualifying pointer with 'volatile' 1 warning generated. And indeed, the clang-compiled testcase didn't crash. So, I followed the advice of the warning and now my testcase looks like this: PT_TESTMETHOD(test_expected_crash) { PT_Test_expectCrash(); // crash intentionally int *volatile nptr = 0; int c = *nptr; printf("%d", c); // to prevent optimizing away the crash } This solved my immediate problem, the testcase "works" (aka crashes) with both gcc and clang. I guess because dereferencing the null pointer is undefined behavior, clang is free to compile my first code into something that doesn't crash. The volatile qualifier removes the ability to be sure at compile time that this really will dereference null. Now my questions are: Does this final code guarantee the null dereference actually happens at runtime? Is dereferencing null indeed a fairly portable way for crashing on most platforms?
I wouldn't rely on that method as being robust if I were you. Can't you use abort(), which is part of the C standard and is guaranteed to cause an abnormal program termination event?
The answer refering to abort() was great, I really didn't think of that and it's indeed a perfectly portable way of forcing an abnormal program termination. Trying it with my code, I came across msvcrt (Microsoft's C runtime) implements abort() in a special chatty way, it outputs the following to stderr: This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information. That's not so nice, at least it unnecessarily clutters the output of a complete test run. So I had a look at __builtin_trap() that's also referenced in clang's warning. It turns out this gives me exactly what I was looking for: LLVM code generator translates __builtin_trap() to a trap instruction if it is supported by the target ISA. Otherwise, the builtin is translated into a call to abort. It's also available in gcc starting with version 4.2.4: This function causes the program to exit abnormally. GCC implements this function by using a target-dependent mechanism (such as intentionally executing an illegal instruction) or by calling abort. As this does something similar to a real crash, I prefer it over a simple abort(). For the fallback, it's still an option trying to do your own illegal operation like the null pointer dereference, but just add a call to abort() in case the program somehow makes it there without crashing. So, all in all, the solution looks like this, testing for a minimum GCC version and using the much more handy __has_builtin() macro provided by clang: #undef HAVE_BUILTIN_TRAP #ifdef __GNUC__ # define GCC_VERSION (__GNUC__ * 10000 \ + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) # if GCC_VERSION > 40203 # define HAVE_BUILTIN_TRAP # endif #else # ifdef __has_builtin # if __has_builtin(__builtin_trap) # define HAVE_BUILTIN_TRAP # endif # endif #endif #ifdef HAVE_BUILTIN_TRAP # define crashMe() __builtin_trap() #else # include <stdio.h> # define crashMe() do { \ int *volatile iptr = 0; \ int i = *iptr; \ printf("%d", i); \ abort(); } while (0) #endif // [...] PT_TESTMETHOD(test_expected_crash) { PT_Test_expectCrash(); // crash intentionally crashMe(); }
you can write memory instead of reading it. *((int *)0) = 0;
No, dereferencing a NULL pointer is not a portable way of crashing a program. It is undefined behavior, which means just that, you have no guarantees what will happen. As it happen, for the most part under any of the three main OS's used today on desktop computers, that being MacOS, Linux and Windows NT (*) dereferencing a NULL pointer will immediately crash your program. That said: "The worst possible result of undefined behavior is for it to do what you were expecting." I purposely put a star beside Windows NT, because under Windows 95/98/ME, I can craft a program that has the following source: int main() { int *pointer = NULL; int i = *pointer; return 0; } that will run without crashing. Compile it as a TINY mode .COM files under 16 bit DOS, and you'll be just fine. Ditto running the same source with just about any C compiler under CP/M. Ditto running that on some embedded systems. I've not tested it on an Arduino, but I would not want to bet either way on the outcome. I do know for certain that were a C compiler available for the 8051 systems I cut my teeth on, that program would run fine on those.
The program below should work. It might cause some collateral damage, though. #include <string.h> void crashme( char *str) { char *omg; for(omg=strtok(str, "" ); omg ; omg=strtok(NULL, "") ) { strcat(omg , "wtf"); } *omg =0; // always NUL-terminate a NULL string !!! } int main(void) { char buff[20]; // crashme( "WTF" ); // works! // crashme( NULL ); // works, too crashme( buff ); // Maybe a bit too slow ... return 0; }
FILE * ..=stdout : Error initializer element is not constant
My C code was as following: [Linux:/si/usr/hrl]vi test.c #include <stdio.h> FILE * hw = stdout; int main(void) { return 0; } When I compile on SUSE , it make the error like that: [Linux:/si/usr/hrl]cc test.c -o test test.c:3: error: initializer element is not constant I have a look for the header file stdio.h and find that stdout seems to have be defined as a constant. So why the error produce?By the way, I compile the same code on AIX ,it results of success.
The standard does not require stdin, stdout and stderr to be constants. The draft n1256 for C99 says in 7.19.1 Input/output <stdio.h> The header declares ... ... TMP_MAX which expands to an integer constant expression ... stderr stdin stdout which are expressions of type ‘‘pointer to FILE’’ ... (emphasize mine) It is explicitely stated that some other values are constant, whereas nothing is said for stdin, stdout and stderr So you must put initialization in main: #include <stdio.h> FILE * hw; int main(void) { hw = stdout; ... return 0; } In AIX standard library, stdout happens to be a constant, but it is just an implementation detail and you cannot rely on that, as it could break in any newer version. But you should not rely either on stdout being a variable (nor even a lvalue), because it is also an implementation detail in GCC library. If you cannot change much of your code, and just need a GCC hack to make it compilable, you could try to use the gcc constructor attribute extension. Extract from gcc documentation 6.31 Declaring Attributes of Functions In GNU C, you declare certain things about functions called in your program which help the compiler optimize function calls and check your code more carefully. The keyword __attribute__ allows you to specify special attributes when making a declaration. This keyword is followed by an attribute specification inside double parentheses. The following attributes are currently defined for functions on all targets: ... ,constructor, ... ... The constructor attribute causes the function to be called automatically before execution enters main () ... So you could use: #include <stdio.h> FILE * hw; void initHw(void) __attribute__((constructor)) { hw = stdout; } int main(void) { return 0; } But BEWARE: it is a gcc extension, meaning that your code is not correct C.