Hello,
I'm wondering if it's possible to make the code below to "seg fault" as I did in the C/C++ code version (below)?
EDIT: Thanks for the replies! Note for future readers: the issue is not with indices being out of bounds, but with the lambda function in C++.
seg_fault_does_not_happen.rs
const NNODE: usize = 3;
fn print_x<'a, F>(num_triangle: usize, get_x: F)
where
F: Fn(usize, usize) -> &'a [f64],
{
for t in 0..num_triangle {
for m in 0..NNODE {
let x = get_x(t, m);
println!("triangle # {}: x = {:?}", t, x);
}
}
}
fn main() {
// [num_triangle][nnode=3][ndim=2]
let triangles = vec![
vec![vec![0.0, 0.0], vec![1.0, 0.0], vec![0.0, 1.0]],
vec![vec![1.0, 0.0], vec![1.2, 1.5], vec![0.0, 1.0]],
];
// closure that returns the coordinates of cell's point i
let get_x = |t: usize, m: usize| &triangles[t][m][..];
// print data
print_x(triangles.len(), get_x);
}
A bit of context: I created the Rust code first (as part of a larger library) and then a friend of mine asked me if I could translate this piece of code to C/C++ so he could use it in his project. So, I had to "re-learn" C/C++ and tried to use the new (to me) lambda functionality. My first try (below), when run, caused a segmentation fault! (with no warnings from the compiler).
seg_fault_happens.cpp
#include <functional>
#include <iostream>
#include <vector>
using namespace std;
const size_t NNODE = 3;
void print_x(size_t num_triangle, function<vector<double> const &(size_t, size_t)> get_x) {
for (size_t t = 0; t < num_triangle; t++) {
for (size_t m = 0; m < NNODE; m++) {
auto x = get_x(t, m);
cout << "triangle # " << t << ": x" << m << " = ";
cout << x[0] << "," << x[1] << endl;
}
}
}
int main() {
try {
// [num_triangle][nnode=3][ndim=2]
vector<vector<vector<double>>> triangles = {
{{0.0, 0.0}, {1.0, 0.0}, {0.0, 1.0}},
{{1.0, 0.0}, {1.0, 1.0}, {0.0, 1.0}}};
// lambda function that returns the coordinates of cell's point i
auto get_x = [&triangles](size_t t, size_t i) {
return triangles[t][i];
};
// print data
print_x(triangles.size(), get_x);
} catch (char const *msg) {
cout << "ERROR: " << msg << endl;
} catch (...) {
cout << "some error occurred" << endl;
}
return 0;
}
Because my work currently is mainly in Rust, I thought that the "move" in the get_x
lambda wasn't right. So, I've made a version with pointers (and not C/C++ references). Now it works:
seg_fault_does_not_happen.cpp
#include <functional>
#include <iostream>
#include <vector>
using namespace std;
const size_t NNODE = 3;
void print_x(size_t num_triangle, function<vector<double> const *(size_t, size_t)> get_x) {
for (size_t t = 0; t < num_triangle; t++) {
for (size_t m = 0; m < NNODE; m++) {
auto x = get_x(t, m);
cout << "triangle # " << t << ": x" << m << " = ";
cout << (*x)[0] << "," << (*x)[1] << endl;
}
}
}
int main() {
try {
// [num_triangle][nnode=3][ndim=2]
vector<vector<vector<double>>> triangles = {
{{0.0, 0.0}, {1.0, 0.0}, {0.0, 1.0}},
{{1.0, 0.0}, {1.0, 1.0}, {0.0, 1.0}}};
// lambda function that returns the coordinates of cell's point i
auto get_x = [&triangles](size_t t, size_t i) {
return &triangles[t][i];
};
// print data
print_x(triangles.size(), get_x);
} catch (char const *msg) {
cout << "ERROR: " << msg << endl;
} catch (...) {
cout << "some error occurred" << endl;
}
return 0;
}
The key difference is return &triangles[t][i];
inside the get_x
lambda.
So, I'm wondering if I could replicate this segfault problem easily in Rust. I hope the answer is NO. The point is that I could tell my friend to "just use Rust and your life will be easier."