我的程序进入分段错误,我找不到原因.最糟糕的是,所讨论的功能并不总是导致段错误.
GDB确认错误并产生这种回溯:
Program received signal SIGSEGV, Segmentation fault.
0xb7da6d6e in malloc_consolidate (av=<value optimized out>) at malloc.c:5169
5169 malloc.c: No such file or directory.
in malloc.c
(gdb) bt
#0 0xb7da6d6e in malloc_consolidate (av=<value optimized out>) at malloc.c:5169
#1 0xb7da9035 in _int_malloc (av=<value optimized out>, bytes=<value optimized out>) at malloc.c:4373
#2 0xb7dab4ac in __libc_malloc (bytes=525) at malloc.c:3660
#3 0xb7f8dc15 in operator new(unsigned int) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#4 0xb7f72db5 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::_Rep::_S_create(unsigned int, unsigned int, std::allocator<char> const&) ()
from /usr/lib/i386-linux-gnu/libstdc++.so.6
#5 …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用libstdc ++(4.6.1)在clang ++(clang 3.1版(trunk 143100))中使用std :: shared_ptr.我有一个小的演示程序:
#include <memory>
int main()
{
std::shared_ptr<int> some(new int);
std::shared_ptr<int> other(some);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
可以使用以下方法构建:
clang++ -std=c++0x -o main main.cpp
Run Code Online (Sandbox Code Playgroud)
并给出以下错误输出:
main.cpp:6:23: error: call to deleted constructor of 'std::shared_ptr<int>'
std::shared_ptr<int> other(some);
^ ~~~~
/usr/include/c++/4.6/bits/shared_ptr.h:93:11: note: function has been explicitly marked
deleted here
class shared_ptr : public __shared_ptr<_Tp>
Run Code Online (Sandbox Code Playgroud)
由于某种原因,它需要删除构造函数,因为提供了移动构造函数(这是正确的行为).但为什么它可以编译(g ++(Ubuntu/Linaro 4.6.1-9ubuntu3)4.6.1.)?有人如何解决这个问题?
Java Native Interface(JNI)是否受C++ ABI兼容性问题的影响?
我正在开发一个Java应用程序.我想使用Java Native Interface(JNI)来调用C++库中的函数.我可以访问C++库的代码,但我可以重建它,但我可能需要.(例如,我可以静态链接C++运行时.)
我可以要求我的用户拥有JRE 6或更高版本,但我不能要求他们拥有任何特定的C++运行时.
一位同事向我指出了这篇博客文章:http://www.trilithium.com/johan/2005/06/static-libstdc/,它建议不要使用动态加载的C++代码.
另一位同事向我指出了这个错误报告:http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4694590,详细说明了如何在Java 1.4.2中解决这些问题.
根据我的理解,问题的要点是libstdc ++的二进制接口经常发生变化.如果C++应用程序加载了使用不同编译器构建的C++共享库,则会同时将两个不兼容的libstdc ++库加载到内存中.
错误报告解释了Java 1.4.2的解决方案:"我们静态链接JDK中的C++运行时并启用链接器脚本以隐藏libstdc ++和其他内部符号中的符号.结果,这些符号对JNI代码变得不可见,并且当某些符号时本机代码需要调用C++运行时,调用将使用适当的libstdc ++解析.所以.还有两个libstdc ++.所以同时加载,但它应该是良性的."
我有几个问题.
首先,OpenJDK是否继续采用这种方法?
[ 编辑:我在OpenJDK的build-dev邮件列表中问过这个问题.答案是肯定的,HotSpot仍然静态地链接libstdc ++,但显然"大多数Linux发行版补丁出来".另一位开发人员指出,这甚至不需要补丁:"设置STATIC_CXX = false应该足够了(默认为true)."]
其次,即使在这种情况下,拥有两个不兼容的libstdc ++是否真的是良性的.所以同时加载?
第三,这种方法(隐藏JDK中的符号)是否解决了所有兼容性问题?
上面引用的博客文章警告说"针对不同ABI编译的代码根本不是二进制兼容的".后来,"语言运行时支持通常依赖于一些共享数据,例如访问某种锁或全局数据结构(类似于C程序需要共享错误的方式)."
这使得听起来无法解决问题.
再说一次,也许ABI不兼容不再是问题.博客文章已有六年多了.另一个stackoverflow问题(GCC ABI兼容性)的答案断言"自从gcc-3.4.0起,ABI是向前兼容的".这是成功的吗?
我对这些问题的任何指导表示感谢.(嘿,谢谢阅读所有这些!)
EDITS
我的问题变得越来越长,所以我没有详细说明.解决威尔的评论:
在C库中math.h,有一个sincos非常有效的函数,因为它在更接近单个调用sin()或者cos()调用两者的总时间的时间内计算正弦和余弦.
C++标准库中有这样的功能吗?
为什么这不编译(尝试使用Clang 3.4.2和GCC版本4.7.4,4.8.3和4.9.1):
#include <exception>
struct E { E(int) {} };
int main() {
std::throw_with_nested(E(42));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
GCC 4.9.1的错误:
In file included from /usr/lib/gcc/x86_64-pc-linux-gnu/4.9.1/include/g++-v4/exception:163:0,
from test.cpp:1:
/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.1/include/g++-v4/bits/nested_exception.h: In instantiation of 'static const std::nested_exception* std::__get_nested_helper<_Ex>::_S_get(const _Ex&) [with _Ex = E]':
/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.1/include/g++-v4/bits/nested_exception.h:104:51: required from 'const std::nested_exception* std::__get_nested_exception(const _Ex&) [with _Ex = E]'
/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.1/include/g++-v4/bits/nested_exception.h:138:38: required from 'void std::throw_with_nested(_Ex) [with _Ex = E]'
test.cpp:6:31: required from here
/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.1/include/g++-v4/bits/nested_exception.h:90:59: error: cannot dynamic_cast '& __ex' (of type 'const struct E*') to type 'const class std::nested_exception*' (source …Run Code Online (Sandbox Code Playgroud) 我打开了-fsanitize=undefined使用Catch(单元测试库)的项目.来自Catch的一行被发信号通知此标志导致未定义的行为.我设法做了一个孤立的例子:
#include <iomanip>
#include <sstream>
int main()
{
std::ostringstream os;
os << "0x" << std::setfill('0') << std::hex;
}
Run Code Online (Sandbox Code Playgroud)
编译:
clang++ -fsanitize=undefined main.cpp
Run Code Online (Sandbox Code Playgroud)
如果我运行它,将给出以下打印:
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/ios_base.h:96:24: runtime error: load of value 4294967221, which is not a valid value for type 'std::_Ios_Fmtflags'
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/ios_base.h:76:67: runtime error: load of value 4294967221, which is not a valid value for type 'std::_Ios_Fmtflags'
Run Code Online (Sandbox Code Playgroud)
这对我来说是clang 3.6.0和一个有clang的朋友3.4-1ubuntu3.在gcc版本上我不会发生这种情况4.9.2
那么这里有什么?这段代码真的很糟糕,还是clang的结尾有什么可疑的?
例如,
#include <random>
struct stru {
//inline static std::mt19937 rnd; Oops!
inline static std::mt19937 rnd{};
};
int main() {
}
Run Code Online (Sandbox Code Playgroud)
我发现两者没有语义差异,而clang在编译两者时没有问题.然而,gcc 8.1为第一个产生以下错误:
prog.cc:4:30: error: no matching function for call to 'std::mersenne_twister_engine<long unsigned int, 32, 624, 397, 31, 2567483615, 11, 4294967295, 7, 2636928640, 15, 4022730752, 18, 1812433253>::mersenne_twister_engine()'
inline static std::mt19937 rnd;
^~~
In file included from /opt/wandbox/gcc-8.1.0/include/c++/8.1.0/random:49,
from prog.cc:1:
/opt/wandbox/gcc-8.1.0/include/c++/8.1.0/bits/random.h:437:11: note: candidate: 'constexpr std::mersenne_twister_engine<long unsigned int, 32, 624, 397, 31, 2567483615, 11, 4294967295, 7, 2636928640, 15, 4022730752, 18, 1812433253>::mersenne_twister_engine(const …Run Code Online (Sandbox Code Playgroud) 使用stl :: vector:
vector<int> v(1);
v[0]=1; // No bounds checking
v.at(0)=1; // Bounds checking
Run Code Online (Sandbox Code Playgroud)
有没有一种方法来禁用边界检查,而不必重写所有at()的[]?我正在使用GNU标准C++库.
编辑:我改变了at()对[]在我怀疑的瓶颈区域,并显著减少了计算时间.但是,由于我在开发代码和运行实验之间进行迭代,我想在开发过程中启用边界检查,并在运行实验时禁用它.我想安德鲁的建议是最好的解决方案.
鉴于这段代码:
#include <mutex>
#include <iostream>
void f(bool doThrow) {
if (doThrow) {
std::cout << "Throwing" << std::endl;
throw 42;
}
std::cout << "Not throwing" << std::endl;
}
std::once_flag flag;
void g(bool doThrow) {
try {
std::call_once(flag, f, doThrow);
std::cout << "Returning" << std::endl;
} catch (int i) {
std::cout << "Caught " << i << std::endl;
}
}
int main() {
std::once_flag flag;
g(true);
g(true);
g(false);
g(true);
g(false);
}
Run Code Online (Sandbox Code Playgroud)
编译时g++ -std=c++11 -pthread -ggdb我得到输出:
Throwing
Caught 42
Run Code Online (Sandbox Code Playgroud)
进程挂起之后:
#0 …Run Code Online (Sandbox Code Playgroud) 为什么这段代码可以在#if 0块就位的情况下工作,但如果删除它,则会失败并显示一组相当复杂的错误消息?更重要的是,我如何使它与上面非常相似的块得到相同的结果?
#include <ranges>
#include <iterator>
#include <optional>
#include <string_view>
#include <iostream>
#include <algorithm>
template <::std::ranges::view View,
typename Pred>
requires ::std::ranges::input_range<View> &&
::std::ranges::common_range<View> &&
::std::is_object_v<Pred> &&
::std::indirect_unary_predicate<const Pred, ::std::ranges::iterator_t<View>>
class skip_after_view : public ::std::ranges::view_interface<skip_after_view<View, Pred>>
{
public:
skip_after_view() = default;
skip_after_view(View v, Pred p)
: subview_(::std::move(v)), pred_(::std::move(p))
{}
class iterator;
friend class iterator;
auto begin() const {
return iterator{subview_.begin(), subview_.end(), &pred_};
}
auto end() const {
return iterator{subview_.end(), subview_.end(), &pred_};
}
private:
View subview_ = View();
Pred pred_; …Run Code Online (Sandbox Code Playgroud) c++ ×10
libstdc++ ×10
g++ ×3
c++11 ×2
clang ×2
abi ×1
c++17 ×1
c++20 ×1
compiler-bug ×1
exception ×1
gcc ×1
inline ×1
java ×1
math ×1
sanitizer ×1
shared-ptr ×1
std-ranges ×1
string ×1
trigonometry ×1
valgrind ×1