簡體   English   中英

EXC_BAD_ACCESS - C++ substr 函數

[英]EXC_BAD_ACCESS - C++ substr function

我有一個使用 c++ substr 的函數。 在 Linux 和 macOS 上,此函數有時會在程序結束時(從單獨的線程調用時)隨機崩潰。

這是函數:

bool mkpath( string path )
{
bool bSuccess = false;
int nRC = ::mkdir( path.c_str(), 0775 );
if( nRC == -1 )
{
    switch( errno )
    {
        case ENOENT:
            //parent didn't exist, try to create it
            if( mkpath( path.substr(0, path.find_last_of('/')) ) )
            {
                //Now, try to create again.
                int status = ::mkdir( path.c_str(), 0775 );
                bSuccess = (0 == status || errno == EEXIST);
            }
            else
            {
                bSuccess = false;
            }
            break;
        case EEXIST:
            //Done!
            bSuccess = true;
            break;
        default:
            bSuccess = false;
            break;
    }
}
else
    bSuccess = true;
return bSuccess;
}

lldb回溯如下:

* thread #4, stop reason = EXC_BAD_ACCESS (code=2, address=0x70000097fff8)
* frame #0: 0x00007fff73d2a81a libsystem_malloc.dylib`tiny_malloc_from_free_list + 8
frame #1: 0x00007fff73d2a297 libsystem_malloc.dylib`tiny_malloc_should_clear + 288
frame #2: 0x00007fff73d290c6 libsystem_malloc.dylib`szone_malloc_should_clear + 66
frame #3: 0x00007fff73d27d7a libsystem_malloc.dylib`malloc_zone_malloc + 104
frame #4: 0x00007fff73d27cf5 libsystem_malloc.dylib`malloc + 21
frame #5: 0x00007fff70ea0dea libc++abi.dylib`operator new(unsigned long) + 26
frame #6: 0x00007fff70e73d70 libc++.1.dylib`std::__1::basic_string<char, 
std::__1::char_traits<char>, std::__1::allocator<char> 
>::basic_string(std::__1::basic_string<char, std::__1::char_traits<char>, 
std::__1::allocator<char> > const&, unsigned long, unsigned long, std::__1::allocator<char> 
const&) + 132
frame #7: 0x0000000103821467 libSampleLibrary.dylib`std::__1::basic_string<char, 
std::__1::char_traits<char>, std::__1::allocator<char> >::substr(unsigned long, unsigned 
long) const + 87
frame #8: 0x0000000103820c77 libSampleLibrary.dylib`mkpath(std::__1::basic_string<char, 
std::__1::char_traits<char>, std::__1::allocator<char> >) + 135
frame #9: 0x0000000103820c80 libSampleLibrary.dylib`mkpath(std::__1::basic_string<char, 
std::__1::char_traits<char>, std::__1::allocator<char> >) + 144
frame #10: 0x0000000103820c80 libSampleLibrary.dylib`mkpath(std::__1::basic_string<char, 
std::__1::char_traits<char>, std::__1::allocator<char> >) + 144
frame #11: 0x0000000103820c80 libSampleLibrary.dylib`mkpath(std::__1::basic_string<char, 
std::__1::char_traits<char>, std::__1::allocator<char> >) + 144
frame #12: 0x0000000103820c80 libSampleLibrary.dylib`mkpath(std::__1::basic_string<char, 
std::__1::char_traits<char>, std::__1::allocator<char> >) + 144
frame #13: 0x0000000103820c80 libSampleLibrary.dylib`mkpath(std::__1::basic_string<char, 
std::__1::char_traits<char>, std::__1::allocator<char> >) + 144
frame #14: 0x0000000103820c80 libSampleLibrary.dylib`mkpath(std::__1::basic_string<char, 
std::__1::char_traits<char>, std::__1::allocator<char> >) + 144
frame #15: 0x0000000103820c80 libSampleLibrary.dylib`mkpath(std::__1::basic_string<char, 
std::__1::char_traits<char>, std::__1::allocator<char> >) + 144
...

這可能發生的任何可能原因? 正如我們添加的那樣,可以從外部取消調用 this 的線程

pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);

在函數中調用此函數的第一行。

每當發生此崩潰時,我都會在回溯中看到以下行超過 5400 次,這非常令人驚訝:

frame #15: 0x0000000103820c80 libSampleLibrary.dylib`mkpath(std::__1::basic_string<char, 
std::__1::char_traits<char>, std::__1::allocator<char> >) + 144

我進一步調試,結果發現一個靜態變量(homePath)被破壞(返回垃圾)。 mkpath() 函數從以下函數中獲取它的值:

string GetSettingFilePath()
{
    static string homePath = "";
    if(!homePath.empty()){
        
        // sometimes homePath variable returns junk at the program exit
        return homePath;
    }

    struct passwd* pwd = getpwuid(getuid());

    if (pwd)
    {
        homePath = pwd->pw_dir;
    }
    else
    {
        // try the $HOME environment variable
        homePath = getenv("HOME");
    }
    if (homePath.empty())
    {
        homePath = "./";
    }
    return homePath
}

由於 homePath 變量雖然設置正確,但有時會在程序退出時返回垃圾,從而導致無限遞歸。 但是為什么函數內的這個靜態變量在程序出口調用時會返回垃圾。

如果您遞歸調用mkpath ,並且path的字符串沒有斜杠/ 那么你將有無限遞歸。

遞歸將是無限的,因為您將mkpath與它已經調用的完全相同的參數調用mkpath

在進行遞歸調用之前,您應該檢查path真的有斜杠/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM