C++ Suspected stack overflow changing function parameters - c++

I am working on implementing a user level thread library in C++ using setcontext(), makecontext(), getcontext(), and swapcontext() on a Linux system.
I am using a wrapper function to wrap the function the user wants to run as a thread. For example, the user calls newthread(funcPtr), and within the thread library funcPtr is passed to a wrapper function that runs it.
The error occurs differently depending on whether or not I initiate an unused string within the function. If I include the line string s = "a"; the program will run to completion, but gdb reveals that context is switching to somewhere within the string library. Without this line, the program segfaults after leaving the function wrapper.
The gdb output shows the corruption of the parameters to function().
I ran valgrind but did not see anything particularly out of the ordinary in the output, just many "Invalid read of size 4" and "Invalid write of size 4" warnings, usually within the C++ standard map.

You could try also AddressSanitizer for debugging. It can detect stack buffer overflows. Here's how to use it on Linux:
At least gcc 4.8 is needed for AddressSanitizer and libasan must be installed (e.g. on Fedora yum install libasan as root). Compile and link with -g -fsanitize=address and run the generated executable. AddressSanitizer stops and emits information if it detects the first error, no long log files have to be analyzed. Solve the reported problem, compile and run again until AddressSanitizer doesn't stop the program anymore. Unfortunately there might be false positives because you use swapcontext in your program, but it's worth a try. Instrumentation can be turned off for a specific function by adding the attribute no_sanitize_address: extern int func(void) __attribute__((no_sanitize_address));

Related

Is it allowed to name a global variable `read` or `malloc` in C++?

Consider the following C++17 code:
#include <iostream>
int read;
int main(){
std::ios_base::sync_with_stdio(false);
std::cin >> read;
}
It compiles and runs fine on Godbolt with GCC 11.2 and Clang 12.0.1, but results in runtime error if compiled with a -static key.
As far as I understand, there is a POSIX(?) function called read (see man read(2)), so the example above actually invokes ODR violation and the program is essentially ill-formed even when compiled without -static. GCC even emits warning if I try to name a variable malloc: built-in function 'malloc' declared as non-function
Is the program above valid C++17? If no, why? If yes, is it a compiler bug which prevents it from running?
The code shown is valid (all C++ Standard versions, I believe). The similar restrictions are all listed in [reserved.names]. Since read is not declared in the C++ standard library, nor in the C standard library, nor in older versions of the standard libraries, and is not otherwise listed there, it's fair game as a name in the global namespace.
So is it an implementation defect that it won't link with -static? (Not a "compiler bug" - the compiler piece of the toolchain is fine, and there's nothing forbidding a warning on valid code.) It does at least work with default settings (though because of how the GNU linker doesn't mind duplicated symbols in an unused object of a dynamic library), and one could argue that's all that's needed for Standard compliance.
We also have at [intro.compliance]/8
A conforming implementation may have extensions (including additional library functions), provided they do not alter the behavior of any well-formed program. Implementations are required to diagnose programs that use such extensions that are ill-formed according to this International Standard. Having done so, however, they can compile and execute such programs.
We can consider POSIX functions such an extension. This is intentionally vague on when or how such extensions are enabled. The g++ driver of the GCC toolset links a number of libraries by default, and we can consider that as adding not only the availability of non-standard #include headers but also adding additional translation units to the program. In theory, different arguments to the g++ driver might make it work without the underlying link step using libc.so. But good luck - one could argue it's a problem that there's no simple way to link only names from the C++ and C standard libraries without including other unreserved names.
(Does not altering a well-formed program even mean that an implementation extension can't use non-reserved names for the additional libraries? I hope not, but I could see a strict reading implying that.)
So I haven't claimed a definitive answer to the question, but the practical situation is unlikely to change, and a Standard Defect Report would in my opinion be more nit-picking than a useful clarification.
Here is some explanation on why it produces a runtime error with -static only.
The https://godbolt.org/z/asKsv95G5 link in the question indicates that the runtime error with -static is Program returned: 139. The output of kill -l in Bash on Linux contains 11) SIGSEGV (and 128 + 11 = 139), so the process exits with fatal signal SIGSEGV (Segmentation fault) indicating invalid memory reference. The reason for that is that the process tries to run the contents (4 bytes) of the read variable as machine code. (Eventually std::cin >> ... calls read.) Either somethings fails in those 4 bytes accidentally interpreted as machine code, or it fails because the memory page containing those 4 bytes is not executable.
The reason why it succeeds without -static is that with dynamic linking it's possible to have multiple symbols with the same name (read): one in the program executable, and another one in the shared library (libc.so.6). std::cin >> ... (in libstdc++.so.6) links against libc.so.6, so when the dynamic linker tries to find the symbol read at program load time (to be used by libstdc++.so.6), it will look at libc.so.6 first, finding read there, and ignoring the read symbol in the program executable.

illegal instruction in boost::gregorian::date::date

I have C++ program that uses boost (Logger mainly). This programs compiles and runs well on Windows and Ubuntu. However, when I try to port it to Linux Yocto on an embedded system (Intel Atom processor), I got illegal instructions error at runtime.
The program itself is built on Ubuntu PC with Intel-i5.
I debugged the issue and it was some AVX instructions from another library (OpenCV). I disabled all AVX and the problem solved but another problem occurred.
It now tells me that (after reading the core dumb using gdb):
Program terminated with signal SIGILL, Illegal instruction.
0x00007fe1aed03ade in boost::gregorian::date::date(boost::gregorian::greg_year,
boost::gregorian::greg_month, boost::gregorian::greg_day) ()
I did not use boost::gregorian::date explicitly
Is it possible that boost::gregorian::date use some optimized insruction?! like SSE or AVX? (seems non-logical)
Any clue about the issue?
P.S. the error occurs at run-time before anything else. Even a cout at the first line of the main function is not executed before I got the error. So, I suspect some static constructor inside boost causes the problem since there is no static constructor at my code.
Edit:
All librires and the program itself are compiled with -march=bonnell -mno-avx -O2

Compile a C++ code snippet using G++ dynamically

Working on a C++ based application, it takes user input and generates a C++ function and compile it to create a .so file and links the function to the main application. Currently had to call an external command "g++" to do it. Wonder if it's possible to call some kind of function, say, "compile" which takes as input an code snippet and produces an .so. More precisely, I need a function that has the following syntax:
sizeOfObjBuf = compile(codeBuf, objBuf);
First parameter is a null terminated string containing a code snippet, the second parameter is the output buffer that hold the compiled code and it returns the size of size of compiled code.
The whole idea is to get rid of dependency on an external program (g++) so the application can run on any Linux system (even when it doesn't have g++ installed).
Thanks.
I'm afraid the answer is "no".
You could implement that function by executing G++ (or some other compiler) in a separate process and waiting for it to finish, but that still requires the user to have a compiler installed.
You can't compile C++ code without a C++ compiler.
I am not going to do the research to figure out how it is done, but I believe the LLVM C++ compiler can be used in this way. All of the parts of LLVM are designed to run as a library, in theory.
OK, a tiny bit of research and I found this: http://clang.llvm.org/docs/LibTooling.html

Eclipse/MinGW/CDT/GDB and problems with debugging

I have some C++ code and try to debug it.
main.cpp:
#include <iostream>
using namespace std;
int main() {
graph<int> a;
a.add(1);
a.addEdge(1,2);
std::vector<int> answ = a.getAdjacent(1);
for (unsigned int i = 0; i < answ.size(); i++)
std::cout<<answ[i]<<std::endl;
return 0;
}
I have a breakpoint on "graph a;". But when I start debugging, I get:
The target endianness is set automatically (currently little endian)
No source file named C:\Users\home\workspace\graphcpp\main.cpp.
[New Thread 3552.0xdc8]
What's the problem?
This seems to be a relatively frequent reoccurring issue when using eclipse +cdt with gdb. Changing the default launcher from GDB (DSF) Create Process to Standard Create Process seems to solve the issue most of the time.
You can find this option under Preferences->Run/Debug->Launching->Default Launchers:
Also make sure you are compiling with -g debug info enabled.
It seems that only with adding the standard parameters to your 'main()' function is enough (I noticed that you're not using parameters in your 'main()':
check this link
I also see this problem. The folks at LinuxQuestions.org helped me make some progress... http://www.linuxquestions.org/questions/showthread.php?t=518283
It appears that gcc 4.1.0 (ie. that in SUSE 10.1, 32-bit) has an optimization where if you don't use argc and argv in the body of main() those symbols are not present in the binary (even with -g and without any special optimization turned on). The 64-bit compiler doesn't do this incidentally.
You get the "Cannot access memory at address 0x0" from the gdb command line if you simply "break main" and print argc in a program that doesn't use argc/argv (and was compiled with gcc 4.1.0). I note your example doesn't use argc/argv.
This is true for C or C++ compilation.
Eclipse is presumably confused by this error in some way when it hits the first break. I was also getting the inability to stop at further breakpoints until I added code to reference argc/argv, or re-declare main (in C++) as "int main(int, char *[])" so that Eclipse wasn't expecting those symbols.
There is still an error in the gdb output window (no symbol "new" in the current context?), but breakpoints can be set.
HTH,
-nick

C++ runtime errors in CodeBlocks when printing strings with cout <<

I recently started using CodeBlocks and began encountering odd runtime errors which I have traced back to printing strings using cout <<. For example, even the following..
#include <string>
#include <iostream>
int main()
{
std::string str;
str = "Hi!";
std::cout << str << std::endl;
return 0;
}
results in an error. It will compile fine (using Borland) but when I run it I get a pop up window saying 'test.exe has stopped working' and in the console I get the message:
Process returned -1073741819 (0xC0000005) execution time : 1.526 s
Press any key to continue.
It compiles and runs fine in MS Visual C++ and with G++ in Ubuntu.. any thoughts would be greatly appreciated!
Cheers,
Weatherwax
My one-off comment ended up helping solve the problem so here it is packaged up as an answer for future users:
This guy had a similar issue and it ended up being a linker issue which he
fixed. The fix is the last post in the thread, although reading the
whole thread could be useful for you.
Long Story short: Borland compiler is a bit dated and annoying to use. Ended up being a linker issue within borland. Better off using a different compiler like GCC/G++ or Visual Studio compiler.
This answer is here to elaborate on the root cause of the issue.
The reason for your crashing program is because the wrong runtime library is being linked. Specifically, your example is compiled as a single threaded object file(the default) but the linking step is using the multithreaded cw32mt.lib runtime -- the "mt" suffix at the end means multithreaded.
The solution is to make sure the runtime your program is compiled to use matches with the runtime you're linking against. A few ways to do this.
Important bcc32 compile switches:
-tW Windows GUI program. WinMain() is expected
-tWC Windows Console program. main() is expected. default.
-tWR Use dynamically linked runtime. Absence implies static runtime linkage.
-tWM Use multithreaded runtime. Absence implies single thread.
Compiling your example program as single threaded like this works:
bcc32 -oexample.obj -c example.cpp
ilink32 -ap example.obj c0x32, example.exe,, cw32.lib import32.lib,,
or you can compile it as multithreaded like this(note the -tWM switch matching up with cw32mt.lib):
bcc32 -tWM -oexample.obj -c example.cpp
ilink32 -ap example.obj c0x32, example.exe,, cw32mt.lib import32.lib,,
A third approach that is easier and less error prone is to not call the linker yourself. Instead, let the compiler drive the linker indirectly(similar to gcc):
bcc32 -tWM -oexample.obj -c example.cpp
bcc32 -tWM example.obj -eexample.exe
For your simple example, it can even be shortened to:
bcc32 -eexample.exe example.cpp
Lastly, you can pass the -tW switch multiple times. For example, this command compiles your example as a console program with multithread support and dynamic runtime linkage:
bcc32 -tWM -tWR -tWC -eexample.exe example.cpp
The produced example.exe executable is much smaller and its import table has an entry for CC3250MT.DLL confirming that the borland runtime is dynamically linked.
We should not assume that a non-functioning program is caused by nonconformity to the standard or a bug in the tool we're using without first investigating user error as a potential cause (even though in this case it's tempting to do so). In the OP's case, the code::block IDE didn't have the right commands setup for the toolchain being used.