2014-11-30 3 views
2

Я уже много часов ломаю голову над этим, и я ничего не могу найти.C/C++ Действительный указатель, но получающий EXC_BAD_ACCESS и KERN_INVALID_ADDRESS

Потенциально соответствующая информация:

  • Бег на OSX 10.10.1 Yosemite

  • Этот же код работает прекрасно на Windows.

  • Каждый раз, когда я запускаю это, он разрывается в том же месте.

  • Приложение представляет собой приложение OpenGL, которое использует glfw3 для создания окна.

  • Нет нитей, это всего лишь однопоточное приложение, поэтому указатель не будет перезаписан или освобожден.

  • Эти два метода содержатся в двух отдельных файлах .c, которые скомпилированы как C++ и содержатся в встроенной библиотеке, к которой я привязываюсь. Другие методы в библиотеке работают очень хорошо.

    OPchar* OPstreamReadLine(OPstream* stream) { 
        OPchar buffer[500]; 
        i32 len, i; 
    
        // ALL WORKS FINE 
         // check to see if we are at the end of the stream or not 
         if(stream->_pointer >= stream->Length) return 0; 
    
         // Prints out the contents of the stream, and the start of the pointer just fine 
         OPlog("Buffer %s | Pointer %d", stream->Data, stream->_pointer); 
         sscanf((OPchar*)stream->Data stream->_pointer, "%500[^\n]", buffer); 
         len = strlen(buffer); 
         stream->_pointer = len 1; 
    
         // Spits out 'Read Hello of len 5' 
         OPlog("Read %s of len %d", buffer, len); 
    
    
    
        // ISSUE STARTS HERE 
        // OPchar is a typedef of char 
        // STEP 1. Make the call 
        OPchar* result = OPstringCreateCopy(buffer); 
    
        // STEP 6. The Pointer is printed out correctly, its the same thing 
        // ex: Pos: 0xd374b4 
        OPlog("Pos: 0x%x", result); 
    
        // STEP 7. This is where it breaks 
        // EXC_BAD_ACCESS and KERN_INVALID_ADDRESS 
        // What happened? 
        // Did returning the pointer from the function break it? 
        OPlog("len: %d", strlen(result)); 
    
        OPlog("Result %s", result); 
    
        return result; 
    } 
    
    
    OPchar* OPstringCreateCopy(const OPchar* str) { 
        i32 len = strlen(str); 
    
        // STEP 2. Prints out 'Hello 5' 
        OPlog("%s %d", str, len); 
    
        // Allocates it (just uses malloc) 
        OPchar* result = (OPchar*)OPalloc(sizeof(OPchar) * (len + 1)); 
    
        // Copies the previous string into the newly created one 
        strcpy(result, str); 
    
        // Ensures that it's null terminated 
        // even though strcpy is supposed to do it 
        result[len] = NULL; 
    
        // STEP 3. Gives a good pointer value 
        // ex: Pos: 0xd374b4 
        OPlog("Pos: 0x%x", result); 
    
        // STEP 4. Prints out '5' 
        OPlog("len: %d", strlen(result)); 
    
        // STEP 5. Prints out 'Hello' 
        OPlog("hmmm: %s", result); 
    
        // Just return this same pointer 
        return result; 
    } 
    

Я с тех пор заменили эти функции с версиями, которые не используют sscanf материал, который получил вокруг этого вопроса, однако я теперь поражая ту же проблему с другой возвращается указатель становится недействительным. Этот пример проще объяснить, поэтому я подумал, что начну там.

+0

Если вам нужно использовать функции форматирования в стиле С, используйте правильные параметры преобразования. % d не является правильным для size_t, а% x не является правильным для указателей. –

+0

И, наконец, если вы не получите никаких предупреждений об этом коде даже при использовании -Wall, рассмотрите вопрос об отправке отчета об ошибке в отношении любого программного обеспечения, предоставляемого OPlog, это их ответственность за то, чтобы вы получали предупреждения. –

ответ

3

Вот теория, которую вы можете протестировать. Вместо того, чтобы использовать %x для печати ваших указателей, вместо этого используйте %p. Вы можете быть в 64-битной ОС и не осознавать ее. Проблема может заключаться в том, что вы не поставляли прототип для OPstringCreateCopy, и в этом случае возвращаемое значение обрабатывалось как int (32 бита) вместо указателя (64 бит). Поскольку вы печатаете только 32 бита result, похоже, что указатель действителен, но верхние 32 бита могут быть потеряны.

Исправить это, чтобы убедиться, что вы всегда поставляете прототипы для всех своих функций. Должны быть какие-то предупреждения о компиляторе, которые вы можете включить, чтобы помочь вам найти использование непрототируемых функций. Вы также можете просмотреть свой код и проверить любые другие 64-разрядные проблемы, например, если вы когда-либо указали на int.

Смежные вопросы