Stack Smashing in GCC vs Clang (Possibly due to canaries) - c++

I am trying to understand possible sources for "stack smashing" errors in GCC, but not Clang.
Specifically, when I compile a piece of code with just debug symbols
set(CMAKE_CXX_FLAGS_DEBUG "-g")
and use the GCC C++ compiler (GNU 5.4.0), the application crashes with
*** stack smashing detected ***: ./testprogram terminated
Aborted (core dumped)
However, when I use Clang 3.8.0, the program completes without error.
My first thought was that perhaps the canaries of GCC are catching a buffer overrun that Clang isn't. So I added the additional debug flag
set(CMAKE_CXX_FLAGS_DEBUG "-g -fstack-protector-all")
But Clang still compiles a program that runs without errors. To me this suggests that the issue likely is not a buffer overrun (as you commonly see with stack smashing errors), but an allocation issue.
In any case, when I add in the ASAN flags:
set(CMAKE_CXX_FLAGS_DEBUG "-g -fsanitize=address")
Both compilers yield a program that crashes with an identical error. Specifically,
GCC 5.4.0:
==1143==ERROR: AddressSanitizer failed to allocate 0xdfff0001000 (15392894357504) bytes at address 2008fff7000 (errno: 12)
==1143==ReserveShadowMemoryRange failed while trying to map 0xdfff0001000 bytes. Perhaps you're using ulimit -v
Aborted (core dumped)
Clang 3.8.0:
==1387==ERROR: AddressSanitizer failed to allocate 0xdfff0001000 (15392894357504) bytes at address 2008fff7000 (errno: 12)
==1387==ReserveShadowMemoryRange failed while trying to map 0xdfff0001000 bytes. Perhaps you're using ulimit -v
Aborted (core dumped)
Can somebody give me some hints on the likely source of this error? I am having an awefully hard time tracing down the line where this is occurring, as it is in a very large code base.
EDIT
The issue is unresolved, but is isolated to the following function:
void get_sparsity(Data & data) {
T x[n_vars] = {};
T g[n_constraints] = {};
for (Index j = 0; j < n_vars; j++) {
const T x_j = x[j];
x[j] = NAN;
eval_g(n_vars, x, TRUE, n_constraints, g, &data);
x[j] = x_j;
std::vector<Index> nonzero_entries;
for (Index i = 0; i < n_constraints; i++) {
if (isnan(g[i])) {
data.flattened_nonzero_rows.push_back(i);
data.flattened_nonzero_cols.push_back(j);
nonzero_entries.push_back(i);
}
}
data.nonzeros.push_back(nonzero_entries);
}
int internal_debug_point = 5;
}
which is called like this:
get_sparsity(data);
int external_debug_point= 6;
However, when I put a debug point on the last line of the get_sparsity function, internal_debug_point = 5, it reaches that line without issue. However, when exiting the function, and before it hits the external debug point external_debug_point = 6, it crashes with the error
received signal SIGABRT, Aborted.
0x00007ffffe315428 in __GI_raise (sig=sig#entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
My guess is that GCC is only checking the canaries when exiting that function, and hence the error is actually occurring inside the function. Does that sound reasonable? If so, then is there a way to get GCC or clang to do more frequent canary checks?

I suspect ASan is running out of memory.
I don't think the ASan errors mean your program is trying to allocate that memory, it means ASan is trying to allocate it for itself (it says "shadow memory" which is what ASan uses to keep track of the memory your program allocates).
If the number of iterations (and size of array) n_vars is large, then the function will use extra memory for a new std::vector in every loop, forcing ASan to track more and more memory.
You could try moving the local vector out of the loop (which will likely increase the performance of the function anyway):
std::vector<Index> nonzero_entries;
for (Index j = 0; j < n_vars; j++) {
// ...
for (Index i = 0; i < n_constraints; i++) {
if (isnan(g[i])) {
data.flattened_nonzero_rows.push_back(i);
data.flattened_nonzero_cols.push_back(j);
nonzero_entries.push_back(i);
}
}
data.nonzeros.push_back(nonzero_entries);
nonzero_entries.clear();
}
This will reuse the same memory for nonzero_entries instead of allocating and deallcoating memory for a new vector every iteration.

Trying to figure out the source of the stack problems was getting nowhere. So I tried a different approach. Through debugging, I narrowed down the above function get_sparsity as the culprit. The debugger wasn't giving me any hints exactly WHERE the problem was occurring, but it was somewhere inside that function. With that information, I switched the only two stack variables in that function x and g to heap variables so that valgrind could help me find the error (sgcheck was coming up empty). Specifically, I modified the above code to
void get_sparsity(Data & data) {
std::vector<T> x(n_vars, 0);
std::vector<T> g(n_constraints, 0);
/* However, for our purposes, it is easier to make an std::vector of Eigen
* vectors, where the ith entry of "nonzero_entries" contains a vector of
* indices in g for which g(indices) are nonzero when perturbing x(i).
* If that sounds complicated, just look at the code and compare to
* the code where we use the sparsity structure.
*/
for (Index j = 0; j < n_vars; j++) {
const T x_j = x[j];
x[j] = NAN;
Bool val = eval_g(n_vars, x.data(), TRUE, n_constraints, g.data(), &data);
x[j] = x_j;
std::vector<Index> nonzero_entries;
for (Index i = 0; i < n_constraints; i++) {
if (isnan(g[i])) {
data.flattened_nonzero_rows.push_back(i);
data.flattened_nonzero_cols.push_back(j);
nonzero_entries.push_back(i);
}
}
data.nonzeros.push_back(nonzero_entries);
}
int bob = 5;
return;
}
and then valgrinded it to find the offending line. Now that I know where the problem is occurring, I can fix the problem.

Related

C++ UndefinedBehaviorSanitizer:DEADLYSIGNAL [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I am trying to solve a problem for code wars, but my code gives an error. I've tested the code on code blocks and it works, but when I test it on their website it gives me some strange error. I looked it on the internet and found out that it might be a segmentation fault because of a deref of a null pointer, but I dont know how to fix it. This is my code and the error. Can you tell me plase what is the problem and why it works on code block, but on the compiler on the website it doesn't.(P.S. Please excuse my english, Im from Romania).
#include <iostream>
#include <vector>
#include <bits/stdc++.h>
using namespace std;
long queueTime(std::vector<int> costumers, int n) {
vector<int> q;
int j, x;
long t;
for (j = 0; j < n; j++)
q.push_back(costumers[j]);
int u = costumers.size();
while (j <= u) {
x = *min_element(q.begin(), q.end());
t = t + x;
for (int i = 0; i < n; i++) {
q[i] = q[i] - x;
if (q[i] == 0) {
q[i] = costumers[j];
j++;
}
}
}
t += *max_element(q.begin(), q.end());
return t;
}
Error message:
UndefinedBehaviorSanitizer:DEADLYSIGNAL
==1==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0x000000000000 (pc 0x00000042547b bp 0x000000000000 sp 0x7ffec8fa0510 T1)
==1==The signal is caused by a READ memory access.
==1==Hint: address points to the zero page.
==1==WARNING: invalid path to external symbolizer!
==1==WARNING: Failed to use and restart external symbolizer!
#0 0x42547a (/workspace/test+0x42547a)
#1 0x427ffc (/workspace/test+0x427ffc)
#2 0x42686e (/workspace/test+0x42686e)
#3 0x426435 (/workspace/test+0x426435)
#4 0x42609b (/workspace/test+0x42609b)
#5 0x42aad5 (/workspace/test+0x42aad5)
#6 0x42581d (/workspace/test+0x42581d)
#7 0x7fc90f605b96 (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
#8 0x404489 (/workspace/test+0x404489)
UndefinedBehaviorSanitizer can not provide additional info.
==1==ABORTING
SEGV would indicate that there is a segmentation fault happening somewhere so you are on the right track with your debugging. Looking at the code you have provided there are few tips that might help you narrow down where things are going wrong.
The first thing that sticks out is that seem to be taking a local copy of costumers on this line:
for (j = 0; j < n; j++) q.push_back(costumers[j]);
Here you make the assumption that n is less or equal to costumers.size() and if n is larger than this then this will try to read from beyond the end of the vector. An alternative here is to use the = operator instead:
vector<int> q = costumers;
If you actually only wanted the first n elements of costumers copied to q then you could use:
if(n < q.size()){
q.resize(n);
}
to shrink it to size afterwards.
Another general style point is that it is good practice to something called "Resource allocation is initialization" (RAII): at the top of your queueTime function you have a bunch of variables declared but not initialized to values:
int j, x;
long t;
The problem here is that these will often be initialized to junk values and if you forget to initialize them later then you may be reading these junk values without knowing. Try instead to declare the variable at the point in the code you assign a value to it, eg fo j:
for(int j = 0; ... )
and x
int x = *min_element(q.begin(), q.end());
or in the case where you need t everywhere in the function scope, at least assign an initial value when you declare it
long t = 0;
Finally when using algorithms that return iterators it is generally good practice to check that they are valid before dereferencing them ie. writing:
auto itr_min_elem = min_element(q.begin(), q.end());
if(itr_min_elem == q.end()){
continue;
}
int x = *itr_min_elem;
so that if q is empty and min_element returns an end iterator then you don't try to dereference it.
Sorry for the wall of text but I hope these offer some help for debugging your function.
As a general note to your question about why it was working on code blocks but not on the website could come down to a number of reasons, likely related to how the code is being compiled. Some compilers will initialize memory to 0s in debug builds and this can have the effect of uninitialized variables behaving nicely in debug but in an undefined way in release. Also depending on the environment the code is executed in there may be differences in the memory layout so reading past the end of an array in one environment may just give junk while in another you may be indexing into protected memory or outside of your programs allocated memory. This would cause the platform running your code to be very unhappy and force it to abort.

(C++) Getting error "Illegal instruction (core dumped)" upon bitwise OR operation

So, I'm still learning about bitwise operations and can't figure out why this error is happening. I've googled it and it appears that this error can happen when messing with the stack, or, in some cases, it has to do with CPU architecture. I've tried compiling with different flags that were supposed to help but I can't get it to work.
Here's the the code quickly:
int corners = 0;
for (int i = 0; i < 8; i++)
{
const ivec3 cornerPos = leaf->min + CHILD_MIN_OFFSETS[i];
const float density = Density_Func(vec3(cornerPos));
const int material = density < 0.f ? MATERIAL_SOLID : MATERIAL_AIR;
corners |= (material << i);
}
And the error "Illegal instruction (core dumped)" is happening at the line
corners |= (material << i);
Here's the output from the debugger:
Signal received: SIGILL (Illegal instruction) For program, pid 26,118
I'm going to give the output of this loop (it never makes it past the first loop).
Here's the code for the couts:
int corners = 0;
std::cout<<"corners(outside loop): "<<corners<<std::endl;
for (int i = 0; i < 8; i++)
{
const ivec3 cornerPos = leaf->min + CHILD_MIN_OFFSETS[i];
std::cout<<"cornerPos.x: "<<cornerPos.x<<std::endl;
std::cout<<"cornerPos.y: "<<cornerPos.y<<std::endl;
std::cout<<"cornerPos.z: "<<cornerPos.z<<std::endl;
const float density = Density_Func(vec3(cornerPos));
std::cout<<"density: "<<density<<std::endl;
const int material = density < 0.f ? MATERIAL_SOLID : MATERIAL_AIR;
std::cout<<"material: "<<material<<std::endl;
std::cout<<"MATERIAL_SOLID: "<<MATERIAL_SOLID<<std::endl;
std::cout<<"MATERIAL_AIR: "<<MATERIAL_AIR<<std::endl;
std::cout<<"i: "<<i<<std::endl;
corners |= (material << i);
std::cout<<"corners(inside loop): "<<corners<<std::endl;
}
and here's the output:
[corners(outside loop): 0] [cornerPos.x: -32] [cornerPos.y: -32] [cornerPos.z: -32] [density: -30] [material: 1] [MATERIAL_SOLID: 1] [MATERIAL_AIR: 0] [i: 0]
I would greatly appreciate any insight someone can give me about why this is happening, and if there is a clear reason, how to go about fixing the problem.
Thank you!
"Illegal instruction" means that CPU was trying to execute instruction which does not understand. This may happen if you compile your program with instruction set which is not supported by your CPU. Crash in this place may suggest that BMI2 bit shift instruction was used (it is supported on CPUs which supports also AVX2). Please check your compilation options.
Another possibility is that your program has overwritten some of its code. It is located at different memory area than stack, so things would be really messed up. I suspect this is not the case here.
This potentially can be also caused by overheating or some CPU bug, but these causes most probably can be excluded here too. The same for possible bug in compiler.

set a breakpoint in malloc_error_break to debug in C++

I'm writing a program that takes 2 command line arguments: a and b respectively.
Everything is good as long as a <= 17.5
As soon as a > 17.5 the program throws the following error:
incorrect checksum for freed object - object was probably modified after being freed
I've narrowed down the problem down to the following piece of code:
for(int a=0; a < viBrickWall.size(); a++) {
vector<int64_t> viTmp(iK-i);
fill(viTmp.begin(),viTmp.end(),2);
for(int b = 0; b < viBrickWall[a].size(); b++) {
viTmp[viBrickWall[a][b]] = 3;
}
viResult.push_back(viTmp);
viTmp.clear();
}
Removing the latter piece of code, gets rid of the error.
I'm also using valgrind to debug the memory, but I haven't been able to find any solution.
Here it is a copy of valgrind's report:
Report hosted in pastebin
EDIT
I compiled the program with debugging flags:
g++ -g -O0 -fno-inline program.cpp
and ran it with valgrind as follows:
` valgrind --leak-check=full --show-reachable=yes --dsymutil=yes ./a.out 48 10 ``
I noticed the following line:
==15318== Invalid write of size 8
==15318== at 0x100001719: iTileBricks(int) (test.cpp:74)
==15318== by 0x100001D7D: main (test.cpp:40)
Line 74 is:
viTmp[viBrickWall[a][b]] = 3;
and Line 40 is:
viBrickWall = iTileBricks(iPanelWidth);
You're causing an invalid write to heap memory with this line:
viTmp[viBrickWall[a][b]] = 3;
this implies that viBrickWall[a][b] is indexing outside of viTmp at that time. Add
int i = viBrickWall[a][b];
assert(0 <= i && i < viTmp.size());
before the store to viTmp[i] = 3.
HINT: maybe increasing the size of viTmp by one would fix it:
-vector<int64_t> viTmp(iK-i);
+vector<int64_t> viTmp(iK - i + 1);
I don't know the content of viBrickWall so this is just an educated guess from the Valgrind output.
I'm not sure if you're using GNU libstdc++ or libc++ on Mac OSX. If you're using libstdc++ or have a Linux box handy, declare viTmp to be a std::__debug::vector would catch this problem quickly.

GDB execution error : argc=<value temporarily unavailable, due to optimizations>, argv=0x7fff5fbff8f8

I've got a problem of execution with a C++ program. First of all, I'm working on a MacBook Pro, using native g++ to compile.
My program builds an array of Record*. Each record has a multidimensional key. Then it iterates over each record to find its unidimensional float key.
In the end, given an interval of two multidimensional keys, it determines if a given float corresponds to a multidimensional key in this interval. The algorithm is taken from a research paper, and it is quite simple in implementation.
Until 100,000 values computed, no problem, the program does its job. But when I goes to 1,000,000 values, execution crashes.Here is the error given by g++ :
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x00007fff5f08dcd0
0x00000001000021ab in TestPyramid () at include/indextree_test.cc:444
Here is the full backtrace given by gdb :
(gdb) backtrace full
#0 0x00000001000021ab in TestPyramid () at include/indextree_test.cc:444
test_records = #1 0x00000001000027be in main (argc=<value temporarily unavailable, due to optimizations>, argv=0x7fff5fbff8f8) at include/indextree_test.cc:83
rc = <value temporarily unavailable, due to optimizations>
progName = 0x7fff5fbff9f8 "/Users/Max/Documents/indextree_test"
testNum = 4
Given lines are calls to the function.
Here is a sample of code :
Record* test_records[1000000];
float values[1000000];
int base = 0;
for (int i(0); i < 1000000; i++)
{
test_records[i] = CreateRecordBasic(i%30+10,i+i%100,"ab","Generic Payload");
if (i%30+10 > base)
base = i%30+10;
if (i+10*i > base)
base = i+10*i;
if (i > base)
base = i;
}
for (int i(0); i < 1000000; i++)
values[i] = floatValueFromKey(test_records[i]->key, base,num_char);
And in the end, I put the relevant float keys in a list.
Is the problem a limitation of my computer ? Did I allocate the memory in a bad manner ?
Thanks for your help,
Max.
Edit :
Here is the code of CreateRecordBasic :
Record *CreateRecordBasic(int32_t attribute_1, int64_t attribute_2, const char* attribute_3, const char* payload){
Attribute** a = new Attribute*[3];
a[0] = ShortAttribute(attribute_1);
a[1] = IntAttribute(attribute_2);
a[2] = VarcharAttribute(attribute_3);
Record *record = new Record;
record->key.value = a;
record->key.attribute_count = 3;
SetValue(record->payload,payload);
return record;
}
Record* test_records[1000000];
float values[1000000];
IMHO, these variables are too big to be stored in the stack whose size is defined by your environment. values takes up 4 megabytes and test_records may take 4-8 megabytes, this is pretty big amount of stack-space. Compiler does not exactly know the size of the system-allocated stack (this may change from system to system) , so you get the error at run-time. Try to allocate them on the heap...

Segmentation fault in neural network

I have been writing a code for a neural network using back propagation algorithm and for propagating inputs I have written the following code,but just for two inputs,its displaying segmentation fault.Is there any wrong withe code.I wan not able to figure it out....
void propagateInput(int cur,int next)
{
cout<<"propagating input"<<cur<<" "<<next<<endl;
cout<<"Number of nerons : "<<neuronsInLayer[cur]<<" "<<neuronsInLayer[next]<<endl;
for(int i = 0;i < neuronsInLayer[next];i++)
{
neuron[next][i].output = 0;
for(int j = 0;j < neuronsInLayer[cur];j++)
{
cout<<neuron[cur][j].output<<" ";
cout<<neuron[next][i].weight[j]<<"\n";
neuron[next][i].output += neuron[next][i].weight[j] * neuron[cur][j].output;
}
cout<<"out["<<i<<"] = "<<neuron[next][i].output<<endl;
}
cout<<"completed propagating input.\n";
}
for(int i = 0;i < neuronsInLayer[next];i++)...
neuronsInLayer[next] is a pointer. perhaps if i knew the type of neuronsInLayer i could assist you more.
That is not anywhere near enough information to debug your code. No info about line numbers or how the structures are laid out in memory or which ones are valid, etc.
So let me tell you how you can find this yourself. If you're using a Unix/Mac then use the GDB debugger on your executable, a.out:
$ gdb a.out
> run
*segfault*
> where
Visual Studio has a great debugger as well, just run it in Debug mode and it'll tell you where the segfault is and let you inspect memory.