【问题标题】:crash at (operator new(unsigned int)+22)在 (operator new(unsigned int)+22) 崩溃
【发布时间】:2019-03-07 07:30:32
【问题描述】:

我正在尝试查找 android 上报告的以下崩溃的原因:

在 (operator new(unsigned int)+22) 处崩溃

这是否意味着内存分配不成功?如果是这样,添加 std::nothrow 和 null 检查并退出程序是正确的解决方案?

有没有办法限制程序不分配以重现它?

崩溃的代码:

glCompileShader( VSID );

GLint vstat;
glGetShaderiv( VSID, GL_COMPILE_STATUS, &vstat );

if( vstat != GL_TRUE )
{
    GLint infolen;
    glGetShaderiv( VSID, GL_INFO_LOG_LENGTH, &infolen );

    GLchar* infostring = new GLchar[infolen + 1];

    glGetShaderInfoLog( VSID, infolen, nullptr, infostring );
    infostring[infolen] = 0;

    std::stringstream Error;
    Error << "An Error occured while trying to compile"\
        " Vertex Shader \"" << VertexShaderPath
        << "\":\n\n" << infostring;
}

【问题讨论】:

  • 我猜是new GLchar[infolen + 1]; 崩溃了? infolen 崩溃时的值是多少?
  • 如果某些函数调用可能触发错误,例如 OpenGL 函数调用,检查错误是一个很好的做法。如果你忽略它们,你就会观察到奇怪的行为。
  • @DanielLangr 你能详细说明一下吗?
  • @dvrer 见khronos.org/opengl/wiki/OpenGL_Error。此外,每个 OpenGL 函数的文档都列出了函数调用可能导致的特定错误。

标签: c++ memory-management opengl-es android-ndk new-operator


【解决方案1】:

运算符newnew[] 崩溃的原因可能是:

  • 分配不成功。例如,如果infolen 与可用内存相比太大。
  • 被分配对象的构造函数崩溃。但是对于GLchar,这不太可能。

您应该添加代码来处理异常,方法是将 new 包含在 try..catch 块中(如 here 所示),以便优雅地终止。

如果你用nothrow 调用new,你应该检查返回的指针是否不同于nullptr,以避免讨厌的UB。

【讨论】:

    【解决方案2】:

    我发现您的代码存在两个问题:首先,您没有检查 glGetShaderiv 是否成功;如果不是,则 infolen 保持未初始化状态。如果在有问题的环境中运行,问题不大,唯一的问题是,您没有使用 glGetShaderInfoLoglength 指针在末尾添加空终止符;检索该值以及进行一致性检查始终是一种好习惯。

    另外我建议你使用std::string 而不是手动分配:

    std::string infostring;
    while( GL_NO_ERROR != glGetError() ); /* Flush Errors */
    
    GLenum err;
    glCompileShader( VSID );
    if( GL_NO_ERROR == (err = glGetError())
    ){
        GLint vstat = 0;
        glGetShaderiv( VSID, GL_COMPILE_STATUS, &vstat );
    
        if( (GL_NO_ERROR == (err = glGetError()))
         && vstat != GL_TRUE
        ){
            GLint infolen = 0;
            glGetShaderiv( VSID, GL_INFO_LOG_LENGTH, &infolen );
            if( (GL_NO_ERROR == (err = glGetError()))
             && 0 < infolen
            ){
                GLsizei returned_infolen = 0;
                infostring = std::string(infolen, 0);
                glGetShaderInfoLog( VSID, infolen, &returned_infolen, infostring.data() );
                infostring.resize(returned_infolen);
    
                err = glGetError();
        }
    }
    if( GL_NO_ERROR != err
    ){
           std::stringstream Error;
            Error << "An Error occured while trying to compile"\
                " Vertex Shader \"" << VertexShaderPath
                << "\":\n\n" << infostring;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多