C++ 使用glut和std::string时,main()前面的分段错误?

C++ 使用glut和std::string时,main()前面的分段错误?,c++,opengl,glut,glu,C++,Opengl,Glut,Glu,在64位Ubuntu14.04LTS上,我试图编译一个使用glut的简单OpenGL程序。在main中执行任何代码行之前,我得到了一个分段错误(SIGSEV);即使是在一个非常精简的测试程序上。这是什么原因造成的 我的命令行: g++-Wall-g main.cpp-lglut-lGL-lGLU-o main 我的简单测试用例: #include <GL/gl.h>

在64位Ubuntu14.04LTS上,我试图编译一个使用glut的简单OpenGL程序。在main中执行任何代码行之前,我得到了一个分段错误(SIGSEV);即使是在一个非常精简的测试程序上。这是什么原因造成的

我的命令行:

g++-Wall-g main.cpp-lglut-lGL-lGLU-o main

我的简单测试用例:

#include <GL/gl.h>                                                                                                                                         
#include <GL/glu.h>
#include <GL/glut.h>

#include <string>
#include <cstdio>

int main(int argc, char** argv){
    printf("Started\n");                                                                                                   
    std::string dummy = "hello";
    glutInit(&argc, argv);
    return 0;
}
然后,在确定了我正在使用的libGL之后,我对它运行了ldd

linux-vdso.so.1 =>  (0x00007ffc55df8000)
libnvidia-tls.so.352.21 => /usr/lib/nvidia-352/tls/libnvidia-tls.so.352.21 (0x00007faa60d83000)
libnvidia-glcore.so.352.21 => /usr/lib/nvidia-352/libnvidia-glcore.so.352.21 (0x00007faa5e2f2000)
libX11.so.6 => /usr/lib/x86_64-linux-gnu/libX11.so.6 (0x00007faa5dfbd000)
libXext.so.6 => /usr/lib/x86_64-linux-gnu/libXext.so.6 (0x00007faa5ddab000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007faa5d9e6000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007faa5d7e2000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007faa5d4dc000)
libxcb.so.1 => /usr/lib/x86_64-linux-gnu/libxcb.so.1 (0x00007faa5d2bd000)
/lib64/ld-linux-x86-64.so.2 (0x00007faa612b5000)
libXau.so.6 => /usr/lib/x86_64-linux-gnu/libXau.so.6 (0x00007faa5d0b9000)
libXdmcp.so.6 => /usr/lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007faa5ceb3000)

但快速浏览并不会发现任何问题。

您的程序和libGL可能与第三个库(可能是libc?)的两个冲突版本相链接或使用。用你提供的细节很难诊断。您可以禁用优化(
-O0
)并查看GDB是否放弃任何进一步的线索。通过运行
ldd
,您可以看到您的程序和libGL都有哪些依赖关系-这显示了编译时依赖关系。抱歉,我只能给出建议-这些类型的运行时问题可能由于多种原因而出现。

因此您可以在LD_调试输出中看到:

它最后输出的内容是:“20863:symbol=\u pthread\u key\u create; 查找文件=/usr/lib/x86_64-linux-gnu/libXdmcp.so.6[0]

这意味着ld.so id正在查找
\uuupthread\ukey\ucreate
,因为它是您的一个库所需要的[您最好找到需要什么库这个符号,它可能会回答什么库需要libpthread.so]

所以
\uuupthread\u key\u create
必须在libpthread.So中,但是在
ldd
输出中没有
libpthread.So
。正如下面所示,您的程序在使用init()中的pthread\u key\u create时可能会崩溃。顺便说一下,您也可以尝试一下

LD_PRELOAD=/lib64/libpthread.so.0 ./main
为了确保在其他符号之前加载
pthread\u key\u create

因此,
lgut
不太可能是问题。它只是在初始化时调用dlsym,这是绝对正确的行为。但程序崩溃:

#0  0x0000000000000000 in ?? ()
#1  0x00007ffff3488291 in init () at dlerror.c:177
#2  0x00007ffff34886d7 in _dlerror_run (operate=operate@entry=0x7ffff3488130 <dlsym_doit>, args=args@entry=0x7fffffffddf0) at dlerror.c:129
(第1帧):

它必须是
\uuuu libc\u key\u create
,这是一个宏,在glibc中有不同的定义。如果您为POSIX构建,它是定义的

/* Create thread-specific key.  */
#define __libc_key_create(KEY, DESTRUCTOR) \
  __libc_ptf_call (__pthread_key_create, (KEY, DESTRUCTOR), 1)
我要求您使用以下工具进行构建:

g++ -pthread -Wall -g main.cpp -lpthread -lglut -lGL -lGLU -o main
为了确保
\uuuu libc\u key\u create
实际上调用了
\uuuu pthread\u key\u create
,并且在-lglut之前初始化了lpthread。但是如果您不想使用-pthread,那么可能需要分析帧1


例如,您可以在您的问题中添加第1帧的拆解

我遇到了一个类似的问题,但是
LD#u PRELOAD=/lib/x86_64-linux-gnu/libpthread.so.0./main
并不总是有效。这个问题发生在NVIDIA GPU上,OpenGL链接到
/usr/lib/NVIDIA-352/libGL.so.1
,在不同的计算机上测试后,我发现改变了g++g++-5的版本可以运行,或者链接到“mesa/libGL.so”,另一个OpenGL实现,通过
g++main.cpp-o main-Wl,--rpath/usr/lib/x86_64-linux-gnu/mesa-lGLU-lGL-lglut

我认为这是因为在printf
argc=1;argv[0]=“测试之前,您没有通过任何args";抱歉,我不能测试它,因为我在火车上。不,如果我通过命令行args,它仍然会中断。因为它在main执行之前就崩溃了,所以无论如何都没有多大意义。请尝试
LD\u DEBUG=all./main
LD\u DEBUG=all LD\u DEBUG\u OUTPUT=log.txt./main
。也许它可以解释一下ld在崩溃前做了什么,当然它提供了大量的信息。差不多9000行。它最后输出的内容是:“20863:symbol=\uu pthread\u key\u create;在文件中查找=/usr/lib/x86\u 64-linux-gnu/libXdmcp.so.6[0]”除此之外,我真的不确定搜索什么;所以有8559行需要筛选,以找到我目前无法识别的东西。好吧,首先,尝试一下。使用
g++-pthread-Wall-gmain.cpp-lglut-lGL-lGLU-o main构建您的项目
感谢您的建议,我尝试了您的两个建议(并用详细信息更新了原始帖子);但我认为我还没有接近揭开谜团。libc在libGL和我的程序之间似乎是相同的(虽然内存地址有所不同,但路径是相同的)。还有其他想法吗?非常感谢!我刚刚醒来,根据你的建议尝试了一些变通办法。我找到了我的libpthread.so并尝试了“LD_PRELOAD=/lib/x86_64-linux-gnu/libpthread.so.0./main”,这很有效!因此,错误正如您所建议的;出于某种原因,libpthread是必需的,但它没有链接到main.cpp`#include void*simpleFunc(void*){return NULL;},我添加了第二个不需要LD_PRELOAD的解决方法,它说服编译器/链接器我确实需要libpthread:我将它添加到main.cpp`#include void*simpleFunc(void*){return NULL;}void forcePThreadLink(){pthread_t t1;pthread_create(&t1,NULL,&simpleFunc,NULL);}'这很愚蠢,但它可以工作。现在,这里的过程是什么:我是否应该接受这个答案(因为它导致了一种变通方法),并提出一个新的问题,为什么在编写一些愚蠢的hack之前,当我明确需要pthread时,我不能链接到pthread?我不确定这个过程。但是你可以发布你自己的答案,如果它是最好的答案,你可以接受它。这两个答案都是
-pthread
-lphread
必需的吗?GCC文档似乎说
-pthread
为预处理器和链接器设置标志。
int
internal_function
_dlerror_run (void (*operate) (void *), void *args)
{
  struct dl_action_result *result;

  /* If we have not yet initialized the buffer do it now.  */
  __libc_once (once, init);
/* Initialize buffers for results.  */
static void
init (void)
{
  if (__libc_key_create (&key, free_key_mem))
    /* Creating the key failed.  This means something really went
       wrong.  In any case use a static buffer which is better than
       nothing.  */
    static_buf = &last_result;
}
/* Create thread-specific key.  */
#define __libc_key_create(KEY, DESTRUCTOR) \
  __libc_ptf_call (__pthread_key_create, (KEY, DESTRUCTOR), 1)
g++ -pthread -Wall -g main.cpp -lpthread -lglut -lGL -lGLU -o main
#1  0x00007ffff3488291 in init () at dlerror.c:177