сбой при (operator new(unsigned int) 22)

#c #memory-management #opengl-es #android-ndk #new-operator

#c #управление памятью #opengl-es #android-ndk #new-оператор

Вопрос:

я пытаюсь найти причину следующего сбоя, о котором сообщается на Android:

сбой при (operator new(unsigned int) 22)

означает ли это, что память не была выделена успешно? и если это так, добавление std::nothrow и проверки null и выход из программы — правильное решение?

есть ли способ, которым я могу ограничить программу, чтобы она не выделялась, чтобы воспроизвести ее?

код, в котором происходит сбой :

 glCompileShader( VSID );

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

if( vstat != GL_TRUE )
{
    GLint infolen;
    glGetShaderiv( VSID, GL_INFO_LOG_LENGTH, amp;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
        << "":nn" << infostring;
}
  

Комментарии:

1. Я полагаю, это new GLchar[infolen 1]; сбой? Каково значение infolen при сбое?

2. Рекомендуется проверять наличие ошибок, если их могут вызвать некоторые вызовы функций, такие как вызовы функций OpenGL. Если вы проигнорируете их, вы можете наблюдать странное поведение.

3. @DanielLangr не могли бы вы подробнее рассказать?

4. @dvrer Смотри khronos.org/opengl/wiki/OpenGL_Error . Кроме того, в документации для каждой функции OpenGL перечислены конкретные ошибки, к которым может привести вызов функции.

Ответ №1:

Сбой в operator new или new[] может быть вызван:

  • неудачное выделение. Например, если infolen слишком большой по сравнению с доступной памятью.
  • сбой в конструкторе выделяемых объектов. Но с GLchar это маловероятно.

Вы должны добавить код для обработки исключения, заключив new в блок try .. catch (как показано здесь), чтобы завершить работу корректно.

Если вы вызываете new с помощью nothrow , вам следует затем проверить возвращаемый указатель на то, что он отличается от nullptr , чтобы избежать неприятного UB.

Ответ №2:

Я вижу две проблемы с вашим кодом: во-первых, вы не проверяете, glGetShaderiv успешно или нет; если нет, то infolen остается неинициализированным. Меньшая проблема и единственная проблема при работе в средах с ошибками заключается в том, что вы не используете length указатель glGetShaderInfoLog для добавления нулевого ограничителя в конце; всегда рекомендуется извлекать это значение, а также проверять согласованность.

Также я предлагаю вам использовать 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, amp;vstat );

    if( (GL_NO_ERROR == (err = glGetError()))
     amp;amp; vstat != GL_TRUE
    ){
        GLint infolen = 0;
        glGetShaderiv( VSID, GL_INFO_LOG_LENGTH, amp;infolen );
        if( (GL_NO_ERROR == (err = glGetError()))
         amp;amp; 0 < infolen
        ){
            GLsizei returned_infolen = 0;
            infostring = std::string(infolen, 0);
            glGetShaderInfoLog( VSID, infolen, amp;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
            << "":nn" << infostring;
}