Исключение из-за ошибки чтения / записи в память

0

Мой код нестабилен: иногда все нормально, и иногда выдает память ошибок чтения/записи или _CrtIsValidHeapPointer. Когда я запускаю программу в "Release build", она вылетает во втором повторении действий, описанных в main(). Но когда его запуск в режиме "Debug" в "Release build" с точками останова при каждом действии - все работает нормально даже после три итерации main(). Тем не менее, нет стабильности. Я не знаю, что с этим случилось. Помоги пожалуйста.

PS Я воссоздаю вопрос.

main.cpp

int main(...)
{
    // ...
    std::vector<CResource> m_aRes;
    uint8 testBuf[70000];

    m_aRes.push_back(CResource(70000));
    m_aRes.back().SetName("Test Name");
    m_aRes.back().SetType("Test Type");
    m_aRes.back().AppendData(testBuf, 70000);
    // ...
}

CResource.h

class CResource
{
protected:
    std::string m_sName;    
    std::string m_sSubName; 
    std::string m_sType;

    std::vector<uint8> m_Data;
UINT               m_DataLen;
public:
    CResource(UINT size);
    ~CResource();   

    void          SetName(char * name);
    void          SetType(char * type);
    const char *  GetName(void);
    const char *  GetType(void);
    const char *  GetSubName(void);
    bool          IsWhole(void);
    UINT          AppendData(uint8 * data, UINT len);
    uint8 *       GetData(void);
    UINT          GetDataLen(void);
    UINT          GetDataLenTemp(void);
};

CResource.cpp

CResource::CResource(UINT size)
{
    m_sName.clear();
    m_sSubName.clear(); 
    m_sType.clear();    

    m_DataLen = size;
    m_Data.reserve(m_DataLen);
}
CResource::~CResource()
{   
    m_sName.clear();
    m_sName.shrink_to_fit();
    m_sSubName.clear();
    m_sSubName.shrink_to_fit();
    m_sType.clear();
    m_sType.shrink_to_fit();    

    m_Data.clear();
    m_Data.shrink_to_fit(); 
}

void CResource::SetName(char * name)
{
    if(!name) return;

    m_sSubName.clear();
    m_sName = name;

    bool bSubNameFound = false;
    for(UINT i=m_sName.size(); i>0; i--) {
            if(bSubNameFound)
                    m_sSubName.insert(0 , &m_sName[i - 1]);
            if(m_sName[i] == '/')
                    bSubNameFound = true;
    }
}
void CResource::SetType(char * type)
{
    if(!type) return;

    m_sType = type;
}
const char * CResource::GetName(void) 
{ 
    return m_sName.c_str(); 
}
const char * CResource::GetType(void)
{ 
    return m_sType.c_str(); 
}
const char * CResource::GetSubName(void) 
{ 
    return m_sSubName.c_str();
}
bool CResource::IsWhole(void) 
{
    return (m_DataLen > 0 && m_DataLen == m_Data.size()) ? true : false; 
}
UINT CResource::AppendData(uint8 * data, UINT len)
{
    if(!data || !len || IsWhole() || m_DataLen == 0) return NULL;   

    UINT DataLenApp = m_Data.size() + len;

    if(DataLenApp > m_DataLen)                   
    {                                               
            len = m_DataLen - m_Data.size();             
            DataLenApp = m_DataLen;                     
    }   

    UINT nFirstApp = m_Data.size();
    for(UINT i = nFirstApp; i < DataLenApp; i++)
                m_Data.push_back(data[i - nFirstApp]);

    return len;
}
uint8 * CResource::GetData(void) 
{ 
    return m_Data.data(); 
}
UINT CResource::GetDataLen(void) 
{
    return m_DataLen; 
}
UINT CResource::GetDataLenTemp(void) 
{ 
    return m_Data.size();
}
  • 1
    Это очень большой массив, который вы выделяете - иногда вы получаете максимум 64 Кбайт. Есть некоторая разница в управлении памятью между режимами отладки и "обычного" компиляции, которые могут быть здесь задействованы. Я бы попробовал uint8 *testBuf; testBuf = malloc(70000*sizeof(uint8)); для выделения массива и посмотреть, исчезнет ли проблема.
  • 0
    В предыдущей версии мой класс CResource был построен с помощью calloc () и realloc (), без векторов и строк std. Но проблема возникла, и теперь она не опустошает. Я думаю, что std :: vector делает этот вызов malloc или любого другого распределителя.
Показать ещё 3 комментария
Теги:
memory
memory-management

2 ответа

1
Лучший ответ

Пробовал здесь (g++ 4.8.2 - cygwin) нет аварии. Проверьте этот комментарий за хорошее предложение, связанное с вашим сбоем.

Но что вы пытаетесь сделать?

m_DataLen = size;
m_Data.reserve(m_DataLen);

m_DataLen кажется синонимом m_Data.capacity().

Здесь вы запретив перераспределение массива (с IsWhole проверки, что m_Data.size() не равна m_DataLen:

if(!data || !len || IsWhole() || m_DataLen == 0) return NULL; 

Вы должны хотя бы упростить проверку, избегая этого двойного определения m_DataLen и используйте m_Data.capacity().

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

UINT nFirstApp = m_Data.size();
for(UINT i = nFirstApp; i < DataLenApp; i++)
   m_Data.push_back(data[i - nFirstApp]);

Это в основном:

m_Data.insert(m_Data.end(), data, data + (DataLenApp - nFirstApp));

Итак, мое эмпирическое правило: упростите свой код и используйте то, что предлагает STD!

  • 0
    m_Data.capacity () - во-первых, я использую его, но имел ошибки, когда он был случайно изменен на ноль, и я получил неправильный DataLen. С другими замечаниями я согласен и очень вам благодарен! Я изменю свой код Благодарю.
  • 0
    capacity() не должна изменяться на ноль. Это изменится, только если вы reserve() , если вы используете shrink_to_fit () или если вы используете push_back() когда size() == capacity() .
Показать ещё 1 комментарий
0

Попробуйте запустить приложение под Valgrind - это действительно объясняет большинство типичных проблем.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню