在这里和这里之前已经提出了与这个问题中的一个相似的点,并且我知道Google coredump库(我已经评估并发现它缺乏,但是如果我更好地理解这个问题,我可能会尝试并努力).
我想在不中断进程的情况下获取正在运行的Linux进程的核心转储.自然的方法是说:
if (!fork()) { abort(); }
Run Code Online (Sandbox Code Playgroud)
由于分叉进程获得原始进程内存的固定快照副本,因此我应该获得完整的核心转储,并且由于副本使用写时复制,因此通常应该很便宜.但是,这种方法的一个关键缺点是fork()只分叉当前线程,并且原始进程的所有其他线程将不存在于分叉副本中.
我的问题是,是否有可能以某种方式获得其他原始线程的相关数据.我不完全确定如何解决这个问题,但这里有几个我提出的子问题:
包含所有线程堆栈的内存是否仍然可用并在分叉进程中可访问?
是否可以(快速)枚举原始进程中的所有正在运行的线程并存储其堆栈基址的地址?据我了解,Linux上的线程堆栈的基础包含指向内核的线程簿记数据的指针,所以......
使用存储的线程基地址,您能读出分叉进程中每个原始线程的相关数据吗?
如果可能,也许只需要将其他线程的数据附加到核心转储.但是,如果该数据已经在fork的位置丢失,那么这种方法似乎没有任何希望.
我可以使用nullptr关键字作为变量函数的参数吗?如果是这样,它是否经历任何类型的标准转换,结果值的类型是什么?
具体来说,以下是正确的吗?
std::printf("%p", nullptr);
Run Code Online (Sandbox Code Playgroud)
或者它必须是:
std::printf("%p", static_cast<void *>(nullptr));
Run Code Online (Sandbox Code Playgroud) 在C++中,临时值的生命周期可以通过将其绑定到引用来扩展:
Foo make_foo();
{
Foo const & r1 = make_foo();
Foo && r2 = make_foo();
// ...
} // both objects are destroyed here
Run Code Online (Sandbox Code Playgroud)
为什么允许这样做?这解决了什么问题?
我在设计和演变中找不到对此的解释(例如6.3.2:临时工作时间).我也找不到任何关于此的问题(这个问题最接近).
此功能有点不直观,并且具有微妙的故障模式.例如:
Foo const & id(Foo const & x) { return x; } // looks like a fine function...
Foo const & r3 = id(make_foo()); // ... but causes a terrible error!
Run Code Online (Sandbox Code Playgroud)
为什么某些东西可以如此容易和默默地滥用语言的一部分?
更新:这一点可能非常微妙,需要作出一些澄清:我不反对使用"引用绑定临时"的规则.这一切都很好,并且允许我们在绑定引用时使用隐式转换.我要问的是为什么临时的生命受到影响.为了扮演魔鬼的拥护者,我可以声称现有的"终身直到完全表达结束"的规则已经涵盖了使用临时参数调用函数的常见用例.
我的程序如下所示
#include <iostream>
#include <thread>
class A {
public:
void foo(int n ) { std::cout << n << std::endl; }
};
int main()
{
A a;
std::thread t1(&A::foo, std::ref(a), 100);
t1.join();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我使用以下命令编译它时,我得到错误
g++ -o main main.cc -lpthread -std=c++11
Run Code Online (Sandbox Code Playgroud)
错误:
In file included from /usr/local/include/c++/4.8.2/thread:39:0,
from check.cc:2:
/usr/local/include/c++/4.8.2/functional: In instantiation of ‘struct std::_Bind_simple<std::_Mem_fn<void (A::*)(int)>(std::reference_wrapper<A>, int)>’:
/usr/local/include/c++/4.8.2/thread:137:47: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (A::*)(int); _Args = {std::reference_wrapper<A>, int}]’
check.cc:13:42: required from here
/usr/local/include/c++/4.8.2/functional:1697:61: error?no type named …Run Code Online (Sandbox Code Playgroud) 我知道原则上这可能是未定义的行为,但为了处理大型项目,这里是关于GCC的问题:
假设我使用完全相同的编译器安装编译一个转换单元gcc -std=c++98,另一个-std=c++11使用.是否有任何保证可以链接两个目标文件并获得定义良好的程序?
据我所知,由于不同的宏,潜在的问题只能来自库头的不同视图,而这些问题反过来最多只能将新的成员函数添加到标准库类中,而不是成员对象.
这会以某种方式使用不同的语言方言选项编译更大项目的不同部分是否可以接受?
更新:我应该添加一个正交的问题:如何使用两个不同版本的GCC(比如4.3和4.6),但是同一个方言选项(-std=c++98)?此GCC文档中的列表似乎表明该库在4.2.2和4.6之间兼容.
我希望这个标题能够真正描述我想要问的内容......
我编写了一段代码,用gcc编译并按照我的意图工作.但是,它不使用llvm编译,并且在使用icc编译时代码执行方式不同!
以下是问题的示例:
#include <iostream>
using std::cout; using std::endl;
class A {
public:
virtual void foo() { cout << "A::foo()" << endl; }
};
class B : public A {
public:
typedef A base;
virtual void foo() { cout << "B::foo()" << endl; }
};
int main() {
typedef B base;
base* bp = new B();
bp->base::foo();
}
Run Code Online (Sandbox Code Playgroud)
gcc输出:A :: foo()
icc输出:B :: foo()
有人可以解释标准对这个案子的看法吗?
我在x86_64 Linux上使用GCC 4.8和glibc 2.19.
在为不同的问题使用不同的输入法时,我比较fscanf和sscanf.具体来说,我要fscanf直接使用标准输入:
char s[128]; int n;
while (fscanf(stdin, "%127s %d", s, &n) == 2) { }
Run Code Online (Sandbox Code Playgroud)
或者我首先将整个输入读入缓冲区然后遍历缓冲区sscanf.(将所有内容读入缓冲区需要花费很少的时间.)
char s[128]; int n;
char const * p = my_data;
for (int b; sscanf(p, "%127s %d%n", s, &n, &b) == 2; p += b) { }
Run Code Online (Sandbox Code Playgroud)
令我惊讶的是,该fscanf版本是大大加快.例如,处理数以万计的行fscanf需要这么长时间:
10000 0.003927487 seconds time elapsed
20000 0.006860206 seconds time elapsed
30000 0.007933329 seconds time elapsed
40000 0.012881912 …Run Code Online (Sandbox Code Playgroud) 我遇到了以下情况:
struct Foo
{
static constexpr char s[] = "Hello world";
};
const char Foo::s[];
Run Code Online (Sandbox Code Playgroud)
这段代码片段与Clang 3.7编译(带-std=c++11和-std=c++14),但GCC(4.8,6.0,相同的语言设置)给出了我预期的错误:
GCC 4.8:
in.cpp:6:19: error: redeclaration ‘Foo::s’ differs in ‘constexpr’
const char Foo::s[];
^
in.cpp:3:27: error: from previous declaration ‘Foo::s’
static constexpr char s[] = "Hello world";
^
in.cpp:6:19: error: declaration of ‘constexpr const char Foo::s [12]’ outside of class is not definition [-fpermissive]
const char Foo::s[];
Run Code Online (Sandbox Code Playgroud)
GCC 6.0:
‘constexpr’ needed for in-class initialization of static data member ‘const char …Run Code Online (Sandbox Code Playgroud) 假设我有一些类型的对象T,我想把它放到一个引用包装器中:
int a = 5, b = 7;
std::reference_wrapper<int> p(a), q(b); // or "auto p = std::ref(a)"
Run Code Online (Sandbox Code Playgroud)
现在我可以很容易地说if (p < q),因为引用包装器已转换为其包装类型.一切都很开心,我可以处理一组参考包装器,就像它们是原始对象一样.
(正如下面链接的问题所示,这可以是生成现有集合的备用视图的有用方法,可以随意重新排列,而不会产生完整副本的成本,以及维护原始集合的更新完整性. )
但是,对于某些类,这不起作用:
std::string s1 = "hello", s2 = "world";
std::reference_wrapper<std::string> t1(s1), t2(s2);
return t1 < t2; // ERROR
Run Code Online (Sandbox Code Playgroud)
我的解决方法是在这个答案中定义一个谓词*; 但我的问题是:
为什么以及何时可以将运算符应用于引用包装器并透明地使用包装类型的运算符?为什么会失败std::string?它与std::string模板实例的事实有什么关系?
*)更新:根据答案,似乎使用std::less<T>()是一般解决方案.
c++ templates implicit-conversion reference-wrapper template-argument-deduction
与C++不同,C没有概念const_cast.也就是说,没有有效的方法将const限定指针转换为非限定指针:
void const * p;
void * q = p; // not good
Run Code Online (Sandbox Code Playgroud)
首先:这个演员实际上是未定义的行为吗?
无论如何,GCC警告这一点.要制作需要const-cast的"干净"代码(即我可以保证我不会改变内容,但我所拥有的只是一个可变指针),我看到了以下"转换"技巧:
typedef union constcaster_
{
void * mp;
void const * cp;
} constcaster;
Run Code Online (Sandbox Code Playgroud)
用法:u.cp = p; q = u.mp;.
通过这种联盟抛弃常量的C语言规则是什么?我对C的了解只是非常不完整,但我听说C对联合访问比C++要宽松得多,所以虽然我对这个结构有一种不好的感觉,但我想从标准中得到一个论证(C99我想,虽然如果在C11中这已经改变了,那么知道它会很好.