c++ - 如果 new 失败,是否需要检查指针有效性?

标签 c++ pointers

正如标题所说,我知道 new 会抛出一个可以被捕获的异常,但是指针到底发生了什么?它变成NULL?我检查了一些关于 SO 的答案,但没有人解释过。 检查下面的例子,指针保持在堆上?请提供有关此模式的完整信息

#include <windows.h>
#include <cstdlib>
#include <iostream>

using namespace std;

enum eReadMode
{
 //    READ_ONLY,
     READ_WRITE,
    // CREATE_FILE,
   //  CREATE_WRITE_FILE,
};

class CFileStatic
{
private:
    FILE *m_File;
public:
    CFileStatic( LPCTSTR szFileName, eReadMode eMode );
    virtual ~CFileStatic() {};

    bool IsValidFile() const { return( m_File != NULL ); };
    void PrintFile( unsigned int uLine = 0 );
};

CFileStatic::CFileStatic( LPCTSTR szFileName, eReadMode eMode )
{
    if( szFileName )
    {
        if( eMode == READ_WRITE )
            m_File = fopen( szFileName, "r+" );
        else
            printf( "Valid usage of: READ_WRITE only" );
    }
    else
        m_File = NULL;
}     

void CFileStatic::PrintFile( unsigned int uLine )
{
    static unsigned uFindNumber;
    if( uLine == 0 )
    {
        char szBuffer[1024];
        while( fgets( szBuffer, 1024, m_File ) )
        {
               std::cout << szBuffer;
        }
    }
    else
    {
        char szBuffer[1024];
        while( fgets( szBuffer, 1024, m_File ) )
        {
               uFindNumber++;
               if( uFindNumber == uLine )
               {
                   std::cout << szBuffer;
               }
        }
    }

}     


int main( int argc, char *argv[] )
{
    //if new fails, what 'pFile' turns out to be? and do I need to delete
    //it later?
    CFileStatic *pFile = new CFileStatic( "Console.h", READ_WRITE );
    if( pFile->IsValidFile() )
    {
        pFile->PrintFile(2);
    }

    CFileStatic *pConsoleCpp = new CFileStatic( "Console.cpp", READ_WRITE );
    if( pConsoleCpp->IsValidFile() )
    {
        pConsoleCpp->PrintFile();
    }


    system("pause>nul");
    return EXIT_SUCCESS;
}

最佳答案

假设您正在使用默认的全局 new 运算符,并且没有使用 newnothrow 版本:

int main( int argc, char *argv[] )
{
  //if new fails, what 'pFile' turns out to be? and do I need to delete
  //it later?
  CFileStatic *pFile = new CFileStatic( "Console.h", READ_WRITE );
  /* ... */
}

没有“后来”。在这段代码中,如果 new 失败,它将抛出一个 std::bad_alloc 异常,您的程序将立即终止。

现在,如果您要尝试处理这种情况,则需要捕获该异常。大概是这样的:

int main( int argc, char *argv[] )
{
  //if new fails, what 'pFile' turns out to be? and do I need to delete
  //it later?
  try
  {
    CFileStatic *pFile = new CFileStatic( "Console.h", READ_WRITE );
  }
  catch( const std::bad_alloc& ex )
  {
    cout << "whoops! out of memory." << ex.what() <<  endl;
  }
  /* ... */
}

pFile 存在于 try block 所包含的范围内,因此它不再存在。移出一层:

  CFileStatic * pFile = 0;
  try
  {
    pFile = new CFileStatic( "Console.h", READ_WRITE );
  }
  catch( const std::bad_alloc& ex )
  {
    cout << "whoops! out of memory." << ex.what() <<  endl;
  }

  // pFile is still 0

pFile 从未被修改,因此值不变。


关于delete指针的问题。标准说 (C++03 5.3.5/2):

[...] if the value of the operand of delete is the null pointer the operation has no effect.

您不必删除 NULL 指针,因为没有什么可删除,但这样做不会有任何效果。你可以安全地这样做:

CFileStatic * pFile = 0;
try
{
  pFile = new CFileStatic( "Console.h", READ_WRITE );
}
catch( const std::bad_alloc& ex )
{
  cout << "whoops! out of memory." << ex.what() <<  endl;
}

delete pFile;  // regardless of the success of new, this is OK

请注意,执行此操作时,将 pFile 初始化为空指针尤为重要,正如我在此处所做的那样。如果你不这样做:

CFileStatic* pFile; // NO INIT
/* ... */
delete pFile; // if new threw, this is undefined behavior

pFile 仍然是垃圾指针。它不是空指针,因此 delete 将尝试删除它,从而导致未定义的行为。

关于c++ - 如果 new 失败,是否需要检查指针有效性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11089986/

相关文章:

c++ - 制作 : No targets provided near line 28 (CMake)

c++ - 带参数的 Pthread 成员函数

c++ - 避免在头文件中包含私有(private)方法所需的内容

c++ - 运算符优先级和指针算法

c - 是否可以将 void * 转换为 char **?

c++ - 如何将 ATL com 类对象作为参数传递给 COM

C++ 最小最大失败

循环精确模型指针和数组

c++ - 如何在 C++ 中使用指针的方法?

string - 如何将 D 中的 char* 转换为字符串?