zry@huawei:~/src/modules/Connect$ ./newbuild/OpConnectAidTool
\WARNING: MYSQL_OPT_RECONNECT is deprecated and will be removed in a future version.
replace into `process_tracking` (`step_id`,`date`,`status`,`context_data`,`start_time`,`end_time`,`error_log`) values(?,?,?,?,?,?,?)
Incorrect datetime value: '' for column 'end_time' at row 1
WARNING: MYSQL_OPT_RECONNECT is deprecated and will be removed in a future version.
replace into `process_tracking` (`step_id`,`date`,`status`,`context_data`,`start_time`,`end_time`,`error_log`) values(?,?,?,?,?,?,?)
=================================================================
==212612==ERROR: AddressSanitizer: stack-use-after-scope on address 0xffffc8f31e50 at pc 0xffff978997b0 bp 0xffffc8f312d0 sp 0xffffc8f31348
READ of size 11 at 0xffffc8f31e50 thread T0#0 0xffff978997ac in __interceptor_strlen ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:354#1 0xffff977bb6c4 in redisFormatSdsCommandArgv /root/temp-z/hiredis-master/hiredis.c:600#2 0xffff977bcce0 in redisAppendCommandArgv /root/temp-z/hiredis-master/hiredis.c:1164#3 0xffff977bcec4 in redisCommandArgv /root/temp-z/hiredis-master/hiredis.c:1216#4 0xaaaaad90210c in zryMyRedisTool::cleanExpiredFields(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) (/home/zry/src/modules/Connect/newbuild/OpConnectAidTool+0x10310c)#5 0xaaaaad8dc744 in CConnectModuleAidTool::SaveProcessTrackingInfo(bool) /home/zry/src/modules/Connect/OpConnectAidTool.cpp:485#6 0xaaaaad8de9d0 in test_SaveProcessTrackingInfo() /home/zry/src/modules/Connect/OpConnectAidTool.cpp:521#7 0xaaaaad8dea0c in main /home/zry/src/modules/Connect/OpConnectAidTool.cpp:535#8 0xffff96c9ae0c in __libc_start_main ../csu/libc-start.c:308#9 0xaaaaad8d02bc (/home/zry/src/modules/Connect/newbuild/OpConnectAidTool+0xd12bc)Address 0xffffc8f31e50 is located in stack of thread T0 at offset 384 in frame#0 0xaaaaad901bf8 in zryMyRedisTool::cleanExpiredFields(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) (/home/zry/src/modules/Connect/newbuild/OpConnectAidTool+0x102bf8)This frame has 10 object(s):[32, 36) 'cleaned' (line 296)[48, 64) '<unknown>'[80, 96) '<unknown>'[112, 136) '<unknown>'[176, 200) '<unknown>'[240, 264) '<unknown>'[304, 336) 'zsetKey' (line 268)[368, 400) '<unknown>' <== Memory access at offset 384 is inside this variable[432, 464) '<unknown>'[496, 544) 'argv' (line 271)
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-use-after-scope ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:354 in __interceptor_strlen
Shadow bytes around the buggy address:0x200ff91e6370: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x200ff91e6380: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x200ff91e6390: 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 04 f20x200ff91e63a0: 00 00 f2 f2 00 00 f2 f2 00 00 00 f2 f2 f2 f2 f20x200ff91e63b0: 00 00 00 f2 f2 f2 f2 f2 00 00 00 f2 f2 f2 f2 f2
=>0x200ff91e63c0: 00 00 00 00 f2 f2 f2 f2 f8 f8[f8]f8 f2 f2 f2 f20x200ff91e63d0: 00 00 00 00 f2 f2 f2 f2 00 00 00 00 00 00 f3 f30x200ff91e63e0: f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 00 000x200ff91e63f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x200ff91e6400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f1 f10x200ff91e6410: f1 f1 f8 f2 f8 f2 f8 f2 01 f2 01 f2 04 f2 04 f2
Shadow byte legend (one shadow byte represents 8 application bytes):Addressable: 00Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: faFreed heap region: fdStack left redzone: f1Stack mid redzone: f2Stack right redzone: f3Stack after return: f5Stack use after scope: f8Global redzone: f9Global init order: f6Poisoned by user: f7Container overflow: fcArray cookie: acIntra object redzone: bbASan internal: feLeft alloca redzone: caRight alloca redzone: cbShadow gap: cc
==212612==ABORTING
2.1 報錯描述
在運行程序時,AddressSanitizer 報告了stack-use-after-scope
錯誤,具體表現為程序試圖訪問已經超出作用域的棧內存。這通常是因為某些變量的作用域問題導致的。
2.2 報錯現象
運行程序時,AddressSanitizer 報告以下錯誤:
==212612==ERROR: AddressSanitizer: stack-use-after-scope on address 0xffffc8f31e50 at pc 0xffff978997b0 bp 0xffffc8f312d0 sp 0xffffc8f31348
READ of size 11 at 0xffffc8f31e50 thread T0
調用棧顯示錯誤發生在zryMyRedisTool::cleanExpiredFields
函數中,具體是在調用redisCommandArgv
時。
2.3 報錯原因
? 變量作用域問題:
? argv
和zsetKey
的作用域可能在調用redisCommandArgv
時已經結束。
? std::vector
的生命周期問題,導致argv.data()
指向的內存無效。
? std::vector
的生命周期問題:
? 如果argv
是一個std::vector
,并且在調用redisCommandArgv
之前被銷毀或重新分配,那么argv.data()
指向的內存可能已經無效。
2.4 報錯分析
2.4.1 確認變量作用域
檢查zryMyRedisTool::cleanExpiredFields
函數中所有變量的作用域,確保在調用redisCommandArgv
時,所有變量仍然有效。
2.4.2 檢查argv
和zsetKey
的生命周期
確保argv
和zsetKey
在調用redisCommandArgv
時仍然有效。可以通過以下方式解決:
? 將argv
和zsetKey
的作用域提升到整個函數。
? 確保argv
和zsetKey
在調用redisCommandArgv
之前不會被銷毀或重新分配。
2.4.3 使用std::vector
的正確方式
如果argv
是一個std::vector
,確保在調用redisCommandArgv
時,argv
的生命周期仍然有效。可以使用std::vector
的data()
方法獲取指針,但需要確保std::vector
不會被重新分配。
2.5 代碼示例
2.5.1 錯誤代碼示例
以下是可能導致問題的代碼示例:
int zryMyRedisTool::cleanExpiredFields(const std::string &hashKey)
{if (cleanup_sha.empty() && !loadCleanupScript()){return -1; // 腳本加載失敗}const std::string zsetKey = hashKey + ":expires";const time_t now = time(nullptr);// argv 的生命周期可能在調用 redisCommandArgv 時已經結束std::vector<const char *> argv = {"EVALSHA",cleanup_sha.c_str(),"2", // KEYS 數量zsetKey.c_str(), // 有序集合鍵 (KEYS[1])hashKey.c_str(), // 哈希鍵 (KEYS[2])std::to_string(now).c_str() // 當前時間戳 (ARGV[1])};redisReply *reply = (redisReply *)redisCommandArgv(context, argv.size(), argv.data(), nullptr);if (!reply){ZRY_LOG_ERROR("cleanExpiredFields failed: no reply");return -1;}// 處理 NOSCRIPT 錯誤(腳本未加載)if (reply->type == REDIS_REPLY_ERROR &&std::strstr(reply->str, "NOSCRIPT") != nullptr){freeReplyObject(reply);cleanup_sha.clear(); // 重置 SHAreturn cleanExpiredFields(hashKey); // 重試}// 處理正常響應int cleaned = -1;if (reply->type == REDIS_REPLY_INTEGER){cleaned = reply->integer;ZRY_LOG_INFO("Cleaned {} fields from {}", cleaned, hashKey);}else if (reply->type == REDIS_REPLY_ERROR){ZRY_LOG_ERROR("Cleanup error: {}", reply->str);}freeReplyObject(reply);return cleaned;
}
2.5.2 修復代碼示例
以下是修復后的代碼示例:
int zryMyRedisTool::cleanExpiredFields(const std::string &hashKey)
{if (cleanup_sha.empty() && !loadCleanupScript()){return -1; // 腳本加載失敗}std::string zsetKey = hashKey + ":expires"; // 確保 zsetKey 的生命周期const time_t now = time(nullptr);std::vector<const char *> argv = {"EVALSHA",cleanup_sha.c_str(),"2", // KEYS 數量zsetKey.c_str(), // 有序集合鍵 (KEYS[1])hashKey.c_str(), // 哈希鍵 (KEYS[2])std::to_string(now).c_str() // 當前時間戳 (ARGV[1])};redisReply *reply = (redisReply *)redisCommandArgv(context, argv.size(), argv.data(), nullptr);if (!reply){ZRY_LOG_ERROR("cleanExpiredFields failed: no reply");return -1;}// 處理 NOSCRIPT 錯誤(腳本未加載)if (reply->type == REDIS_REPLY_ERROR &&std::strstr(reply->str, "NOSCRIPT") != nullptr){freeReplyObject(reply);cleanup_sha.clear(); // 重置 SHAreturn cleanExpiredFields(hashKey); // 重試}// 處理正常響應int cleaned = -1;if (reply->type == REDIS_REPLY_INTEGER){cleaned = reply->integer;ZRY_LOG_INFO("Cleaned {} fields from {}", cleaned, hashKey);}else if (reply->type == REDIS_REPLY_ERROR){ZRY_LOG_ERROR("Cleanup error: {}", reply->str);}freeReplyObject(reply);return cleaned;
}
2.6 Mermaid 圖表
2.7 其他注意事項
? MySQL 警告:
WARNING: MYSQL_OPT_RECONNECT is deprecated and will be removed in a future version.
這是一個 MySQL 的警告,表明MYSQL_OPT_RECONNECT
已經被棄用,建議使用其他方式來處理重連邏輯。
? SQL 錯誤:
Incorrect datetime value: '' for column 'end_time' at row 1
這是一個 SQL 錯誤,表明在插入數據時,end_time
列的值為空字符串,而該列可能需要一個有效的日期時間值。需要檢查代碼中對end_time
的賦值邏輯,確保其值有效。
2.8 總結
通過確保argv
和zsetKey
的生命周期,可以解決stack-use-after-scope
的問題。同時,需要檢查 MySQL 的重連邏輯和 SQL 插入語句的合法性,以避免其他潛在問題。