مهمترین و رایجترین خطا در کار با std::string_view، به ماهیت غیرمالک بودن آن بازمیگردد. از آنجا که یک string_view
صرفاً یک نمای (view) از دادههای موجود است و مالک آن دادهها نیست، در
صورت از بین رفتن منبع داده، نمای شما به یک اشارهگر آویزان (dangling
pointer) تبدیل میشود که دسترسی به آن رفتار تعریفنشده (UB) به همراه
دارد. این مسئله بهقدری حیاتی است که ابزارهای تحلیل کد مانند clang-tidy چککنندههای خاصی مانند bugprone-dangling-handle برای شناسایی این نوع خطاها ارائه دادهاند .
دام اصلی: ساخت از روی اشیاء موقت
یکی از رایجترین صحنههای بروز این خطا، ساخت یک string_view
از روی یک شیء موقت (temporary) مانند رشتهای که حاصل یک عملگر یا یک
تابع است، میباشد. پس از پایان دستور (statement)، شیء موقت نابود شده و
نمای شما به فضای حافظهای آزاد شده اشاره میکند . همچنین در زبان ++C، دستهی مقدار (value category) معادل طول عمر نیست
و کامپایلر بهطور خودکار از این نوع خطاها جلوگیری نمیکند، زیرا این
طراحی بهعمد برای حفظ عملکرد بالا و انعطافپذیری صورت گرفته است و
مسئولیت مدیریت طول عمر را بر عهدهی برنامهنویس میگذارد .
خطاهای رایج در استفاده از متد data()
استفاده از متد data() یکی دیگر از منابع اصلی بروز خطا است. برخلاف std::string، یک std::string_view تضمین نمیکند که به کاراکتر پایانی null ختم شود . این موضوع زمانی به خطا تبدیل میشود که برنامهنویس، نتیجهی data() را به توابعی که منتظر یک رشتهی null-terminated مانند توابع کتابخانهی C هستند، ارسال کند . مشکل زمانی تشدید میشود که بخواهیم یک string_view را به یک std::string تبدیل کنیم. از آنجا که سازندهی مربوطه در std::string از نوع explicit است، کد بهسادگی کامپایل نمیشود. برنامهنویس ناآشنا، برای رفع خطای کامپایل، ممکن است به استفاده از sv.data() روی آورد که این کار، خطرات اشارهشده را به همراه خواهد داشت .
تغییر منبع داده در حین استفاده
حتی اگر منبع دادهی اصلی نابود نشود، ممکن است محتوای آن تغییر کند. برای نمونه، اگر یک string_view از یک شیء std::string ساخته باشید، هرگونه عملیاتی که باعث تخصیص مجدد حافظه در آن string شود (مانند افزودن کاراکترهای جدید)، میتواند بافر آن را به مکان دیگری در حافظه منتقل کند. در این حالت، string_view شما همچنان به آدرس قدیمی اشاره خواهد کرد که اکنون نامعتبر است .
بازگرداندن std::string_view از توابع
بازگرداندن یک string_view
از یک تابع یکی دیگر از موقعیتهای پرخطر است. اگر نمایی از یک متغیر محلی
تابع بازگردانده شود، پس از خروج از تابع، آن متغیر نابود شده و خروجی
تابع دچار مشکل میشود . تنها دو حالت برای بازگرداندن امن string_view وجود دارد: اول، زمانی که به یک رشتهی ثابت (string literal) اشاره میکند (چون طول عمر آن معادل کل برنامه است) و دوم، زمانی که یکی از پارامترهای ورودی خود تابع را که از نوع string_view است، بازمیگرداند (چون مسئولیت اعتبار دادهها بر عهدهی فراخواننده است) .
الگوی صحیح: View در ورودی، مالکیت در خروجی
بهترین روش برای بهرهمندی از مزایای std::string_view بدون افتادن در دام خطاها، استفاده از آن بهعنوان یک نوع پارامتر برای توابع است که صرفاً نیاز به خواندن داده دارند. در مقابل، برای ذخیرهسازی داده بهعنوان عضو کلاس یا ساختمانها، بهتر است از std::string استفاده شود تا مالکیت دادهها بهوضوح مشخص باشد . بهعنوان مثال، تابعی که یک string_view را بهعنوان ورودی دریافت میکند، باید در صورت نیاز به ذخیرهسازی، یک کپی از آن را بهصورت std::string درون شیء خود ذخیره کند، نه اینکه صرفاً خود string_view را نگه دارد .
کلیدواژه ها : std::string_view lifespan-مدیریت طول عمر string_view-خطاهای رایج string_view-dangling string_view-std::string_view data null terminated-اشارهگر آویزان در C++-بازگرداندن string_view از تابع-std::string_view temporary object-مشکلات string_view-نکات ایمنی string_view-string_view vs string-آموزش string_view-بهینهسازی رشته در C++