C++ segfault,但不在valgrind或gdb中
在我的项目中,有一个库,其中包含使用Autodesk的fbx SDK 2017.1加载fbx的代码 在调试和发布时加载fbx会崩溃。碰撞以两种不同的方式发生,而且似乎是随机发生的:C++ segfault,但不在valgrind或gdb中,c++,segmentation-fault,gdb,valgrind,fbx,C++,Segmentation Fault,Gdb,Valgrind,Fbx,在我的项目中,有一个库,其中包含使用Autodesk的fbx SDK 2017.1加载fbx的代码 在调试和发布时加载fbx会崩溃。碰撞以两种不同的方式发生,而且似乎是随机发生的: 崩溃要么只是“分段故障”(大多数情况下) 崩溃是崩溃中可能涉及的所有库的转储,是对realloc()调用问题的暗示。(每隔一段时间)从消息的上下文中,我无法分辨出可能是哪个realloc(消息后面是链接的所有lib的转储) 代码确实包含realloc()调用,特别是在FbxStream的自定义实现中使用的缓冲区分
- 崩溃要么只是“分段故障”(大多数情况下)
- 崩溃是崩溃中可能涉及的所有库的转储,是对realloc()调用问题的暗示。(每隔一段时间)从消息的上下文中,我无法分辨出可能是哪个realloc(消息后面是链接的所有lib的转储)李>
class MyFbxStream : public FbxStream{
uint32 m_FormatID;
uint32 m_Error;
EState m_State;
size_t m_Pos;
size_t m_Size;
const Engine::Buffer* const m_Buffer;
MyFbxStream& operator = (const MyFbxStream& other) const;
public:
MyFbxStream(const Engine::Buffer* const buffer)
: m_FormatID(0)
, m_Error(0)
, m_State(eClosed)
, m_Pos(0)
, m_Size(0)
, m_Buffer(buffer) {};
virtual ~MyFbxStream() {};
virtual bool Open(void* pStreamData) {
m_FormatID = *(uint32*)pStreamData;
m_Pos = 0;
m_State = eOpen;
m_Size = m_Buffer->GetSize();
return true;
}
virtual bool Close() {
m_Pos = m_Size = 0;
m_State = eClosed;
return true;
}
virtual int Read(void* pData, int pSize) const {
const unsigned char* data = (m_Buffer->GetBase(m_Pos));
const size_t bytesRead = m_Pos + pSize > m_Buffer->GetSize() ? (m_Buffer->GetSize() - m_Pos) : pSize;
const_cast<MyFbxStream*>(this)->m_Pos += bytesRead;
memcpy(pData, data, bytesRead);
return (int)bytesRead;
}
/** Read a string from the stream.
* The default implementation is written in terms of Read() but does not cope with DOS line endings.
* Subclasses may need to override this if DOS line endings are to be supported.
* \param pBuffer Pointer to the memory block where the read bytes are stored.
* \param pMaxSize Maximum number of bytes to be read from the stream.
* \param pStopAtFirstWhiteSpace Stop reading when any whitespace is encountered. Otherwise read to end of line (like fgets()).
* \return pBuffer, if successful, else NULL.
* \remark The default implementation terminates the \e pBuffer with a null character and assumes there is enough room for it.
* For example, a call with \e pMaxSize = 1 will fill \e pBuffer with the null character only. */
virtual char* ReadString(char* pBuffer, int pMaxSize, bool pStopAtFirstWhiteSpace = false) {
assert(!pStopAtFirstWhiteSpace); // "Not supported"
const size_t pSize = pMaxSize - 1;
if (pSize) {
const char* const base = (const char* const)m_Buffer->GetBase();
char* cBuffer = pBuffer;
const size_t totalSize = std::min(m_Buffer->GetSize(), (m_Pos + pSize));
const char* const maxSize = base + totalSize;
const char* sum = base + m_Pos;
bool done = false;
// first align the copy on alignment boundary (4byte)
while ((((size_t)sum & 0x3) != 0) && (sum < maxSize)) {
const unsigned char c = *sum++;
*cBuffer++ = c;
if ((c == '\n') || (c == '\r')) {
done = true;
break;
} }
// copy from alignment boundary to boundary (4byte)
if (!done) {
int64 newBytesRead = 0;
uint32* dBuffer = (uint32*)cBuffer;
const uint32* dBase = (uint32*)sum;
const uint32* const dmaxSize = ((uint32*)maxSize) - 1;
while (dBase < dmaxSize) {
const uint32 data = *(const uint32*const)dBase++;
*dBuffer++ = data;
if (((data & 0xff) == 0x0a) || ((data & 0xff) == 0x0d)) { // third bytes, 4 bytes read..
newBytesRead -= 3;
done = true;
break;
} else {
const uint32 shiftedData8 = data & 0xff00;
if ((shiftedData8 == 0x0a00) || (shiftedData8 == 0x0d00)) { // third bytes, 3 bytes read..
newBytesRead -= 2;
done = true;
break;
} else {
const uint32 shiftedData16 = data & 0xff0000;
if ((shiftedData16 == 0x0a0000) || (shiftedData16 == 0x0d0000)) { // second byte, 2 bytes read..
newBytesRead -= 1;
done = true;
break;
} else {
const uint32 shiftedData24 = data & 0xff000000;
if ((shiftedData24 == 0x0a000000) || (shiftedData24 == 0x0d000000)) { // first byte, 1 bytes read..
done = true;
break;
} } } } }
newBytesRead += (int64)dBuffer - (int64)cBuffer;
if (newBytesRead) {
sum += newBytesRead;
cBuffer += newBytesRead;
} }
// copy anything beyond the last alignment boundary (4byte)
if (!done) {
while (sum < maxSize) {
const unsigned char c = *sum++;
*cBuffer++ = c;
if ((c == '\n') || (c == '\r')) {
done = true;
break;
} } }
const size_t bytesRead = cBuffer - pBuffer;
if (bytesRead) {
const_cast<MyFbxStream*>(this)->m_Pos += bytesRead;
pBuffer[bytesRead] = 0;
return pBuffer;
} }
pBuffer = NULL;
return NULL;
}
virtual void Seek(const FbxInt64& pOffset, const FbxFile::ESeekPos& pSeekPos) {
switch (pSeekPos) {
case FbxFile::ESeekPos::eBegin: m_Pos = pOffset; break;
case FbxFile::ESeekPos::eCurrent: m_Pos += pOffset; break;
case FbxFile::ESeekPos::eEnd: m_Pos = m_Size - pOffset; break;
}
}
virtual long GetPosition() const { return (long)m_Pos; }
virtual void SetPosition(long position) { m_Pos = position; }
virtual void ClearError() { m_Error = 0; }
virtual int GetError() const { return m_Error; }
virtual EState GetState() { return m_State; }
virtual int GetReaderID() const { return m_FormatID; }
virtual int GetWriterID() const { return -1; } // readonly stream
virtual bool Flush() { return true; } // readonly stream
virtual int Write(const void* /*d*/, int /*s*/) { assert(false); return 0; } // readonly stream
};
class MyFbxStream:public FbxStream{
uint32 m_FormatID;
uint32 m_错误;
m_州房地产;
尺寸m位置;
大小;
常量引擎::缓冲区*常量m_缓冲区;
MyFbxStream和operator=(常量MyFbxStream和其他)常量;
公众:
MyFbxStream(常量引擎::缓冲区*常量缓冲区)
:m_FormatID(0)
,m_错误(0)
,m_州(已关闭)
,m_Pos(0)
,m_尺寸(0)
,m_Buffer(Buffer){};
虚拟~MyFbxStream(){};
虚拟bool Open(void*pStreamData){
m_FormatID=*(uint32*)流媒体数据;
m_Pos=0;
m_State=eOpen;
m_Size=m_Buffer->GetSize();
返回true;
}
虚拟布尔关闭(){
m_Pos=m_Size=0;
m_状态=已关闭;
返回true;
}
虚拟整数读取(void*pData,int pSize)常量{
常量无符号字符*数据=(m_Buffer->GetBase(m_Pos));
const size\u t bytesRead=m_Pos+pSize>m_Buffer->GetSize()?(m_Buffer->GetSize()-m_Pos):pSize;
const_cast(this)->m_Pos+=bytesRead;
memcpy(pData、data、bytesRead);
返回(int)字节读取;
}
/**从流中读取字符串。
*默认实现是用Read()编写的,但不处理DOS行结尾。
*如果要支持DOS行结束符,子类可能需要重写此选项。
*\param pBuffer指向存储读取字节的内存块的指针。
*\param pmaxize要从流中读取的最大字节数。
*\param pStopAtFirstWhiteSpace遇到任何空白时停止读取。否则读取到行尾(如fgets())。
*\返回pBuffer,如果成功,则返回NULL。
*\remark默认实现使用空字符终止\e pBuffer,并假定有足够的空间容纳它。
*例如,\e pMaxSize=1的调用将只使用空字符填充\e pBuffer*/
虚拟字符*读取字符串(字符*pBuffer,int-pmaxize,bool-pStopAtFirstWhiteSpace=false){
断言(!pStopAtFirstWhiteSpace);//“不受支持”
const size_t pSize=pMaxSize-1;
如果(pSize){
const char*const base=(const char*const)m_Buffer->GetBase();
char*cBuffer=pBuffer;
const size_t totalSize=std::min(m_Buffer->GetSize(),(m_Pos+pSize));
const char*const maxSize=base+totalSize;
const char*sum=base+m_Pos;
bool done=false;
//首先在对齐边界上对齐副本(4字节)
而(((size_t)sum&0x3)!=0)和&(sum