දේශීය විචල්‍යයක මතකය එහි විෂය පථයෙන් පිටත ප්‍රවේශ විය හැකිද?


1044

මට පහත කේතය ඇත.

#include <iostream>

int * foo()
{
    int a = 5;
    return &a;
}

int main()
{
    int* p = foo();
    std::cout << *p;
    *p = 8;
    std::cout << *p;
}

කේතය කිසිදු ධාවන කාල ව්‍යතිරේකයකින් තොරව ක්‍රියාත්මක වේ!

නිමැවුම විය 58

එය විය හැක්කේ කෙසේද? දේශීය විචල්‍යයක මතකය එහි ක්‍රියාකාරීත්වයට පිටතින් ප්‍රවේශ විය නොහැකිද?


14
මෙය සම්පාදනය නොකරනු ඇත; ඔබ අවිධිමත් ව්‍යාපාරය නිවැරදි කරන්නේ නම්, gcc තවමත් අනතුරු අඟවනු ඇත address of local variable ‘a’ returned; valgrind showsInvalid write of size 4 [...] Address 0xbefd7114 is just below the stack ptr
sehe

76
Er සර්ජ්: මගේ යෞවන කාලයේ දී, මම වරක් නෙට්වෙයාර් මෙහෙයුම් පද්ධතිය මත ධාවනය වූ යම් ආකාරයක උපක්‍රමශීලී ශුන්‍ය-මුදු කේතයක් මත වැඩ කළෙමි. මම වැරැද්දක් කළේ කවදාදැයි මම දනිමි, මන්ද බොහෝ විට තොගය තිරයේ මතකය අතිච්ඡාදනය වන අතර බයිට් දර්ශනය මත ලියා ඇති ආකාරය නැරඹිය හැකිය. මේ දිනවල ඔබට එවැනි දේවලින් ගැලවිය නොහැක.
එරික් ලිපර්ට්

23
lol. ගැටලුව තිබෙන්නේ කොතැනදැයි තේරුම් ගැනීමට පෙර මට ප්‍රශ්නය සහ පිළිතුරු කිහිපයක් කියවීමට අවශ්‍ය විය. එය ඇත්ත වශයෙන්ම විචල්යයේ ප්රවේශ විෂය පථය පිළිබඳ ප්රශ්නයක් ද? ඔබ ඔබේ ශ්‍රිතයෙන් පිටත 'a' භාවිතා නොකරයි. ඒ සඳහා ඇත්තේ එපමණකි. සමහර මතක යොමු කිරීම් විසි කිරීම විචල්‍ය විෂය පථයට වඩා සම්පූර්ණයෙන්ම වෙනස් මාතෘකාවකි.
erikbwork

10
ඩුප් පිළිතුරෙන් ඩුප් ප්‍රශ්නය අදහස් නොවේ. මෙහි මිනිසුන් විසින් යෝජනා කරන ලද ඩුප් ප්‍රශ්න බොහොමයක් එකම යටින් පවතින රෝග ලක්ෂණයට යොමු වීමට සම්පූර්ණයෙන්ම වෙනස් ප්‍රශ්න වේ ... නමුත් ප්‍රශ්නකරුවාට එය දැන ගැනීමේ ක්‍රමයක් ඇත, එබැවින් ඒවා විවෘතව තිබිය යුතුය. මම පැරණි ඩුප් එකක් වසා එය විවෘතව තිබිය යුතු මෙම ප්‍රශ්නයට ඒකාබද්ධ කළෙමි. එයට හොඳ පිළිතුරක් ඇත.
ජොයෙල් ස්පොල්ස්කි

16
Oe ජොයෙල්: මෙහි පිළිතුර හොඳ නම්, එය පැරණි ප්‍රශ්න වලට ඒකාබද්ධ කළ යුතු අතර, මෙය ඩුප් එකක් මිස වෙනත් ආකාරයකින් නොවේ. මෙම ප්‍රශ්නය ඇත්ත වශයෙන්ම මෙහි යෝජනා කර ඇති අනෙක් ප්‍රශ්නවල අනුපිටපතක් වන අතර පසුව සමහරක් (යෝජිත සමහරක් අනෙක් ඒවාට වඩා හොඳ සුදුසුකමක් වුවද). එරික්ගේ පිළිතුර හොඳයි කියා මා සිතන බව සලකන්න. (ඇත්ත වශයෙන්ම, පැරණි ප්‍රශ්න
ගැලවීම

Answers:


4818

එය විය හැක්කේ කෙසේද? දේශීය විචල්‍යයක මතකය එහි ක්‍රියාකාරීත්වයට පිටතින් ප්‍රවේශ විය නොහැකිද?

ඔබ හෝටල් කාමරයක් කුලියට ගන්නවා. ඔබ ඇඳ අසල මේසයේ ඉහළ ලාච්චුවේ පොතක් තබා නින්දට යන්න. ඔබ පසුදා උදෑසන පරීක්ෂා කර බලන්න, නමුත් ඔබේ යතුර ආපසු ලබා දීමට "අමතක කරන්න". ඔබ යතුර සොරකම් කළා!

සතියකට පසු, ඔබ නැවත හෝටලයට පැමිණ, පරීක්ෂා නොකරන්න, ඔබේ සොරකම් කළ යතුර සමඟ ඔබේ පැරණි කාමරයට ගොස්, ලාච්චුවේ බලන්න. ඔබේ පොත තවමත් පවතී. පුදුමයි!

එය කෙසේ විය හැකිද? ඔබ කාමරය කුලියට ගෙන නොමැතිනම් හෝටල් කාමර ලාච්චුවක අන්තර්ගතය ප්‍රවේශ කළ නොහැකිද?

හොඳයි, පැහැදිලිවම එම තත්වය සැබෑ ලෝකයේ සිදුවිය හැකි කිසිදු ගැටළුවක් නැත. ඔබට තවදුරටත් කාමරයේ සිටීමට අවසර නොමැති විට ඔබේ පොත අතුරුදහන් වීමට හේතු වන අද්භූත බලයක් නොමැත. සොරකම් කළ යතුරක් සහිත කාමරයකට ඇතුළු වීම වළක්වන අද්භූත බලවේගයක් ද නැත.

ඔබේ පොත ඉවත් කිරීමට හෝටල් කළමනාකරණය අවශ්‍ය නොවේ . ඔබ ඔවුන් සමඟ ගිවිසුමක් ඇති කර නොගත් අතර, ඔබ දේවල් අතහැර දැමුවහොත්, ඔවුන් ඔබ වෙනුවෙන් එය ඉරා දමනු ඇත. සොරකම් කරන ලද යතුරක් සමඟ එය නැවත ලබා ගැනීම සඳහා ඔබ නීති විරෝධී ලෙස ඔබේ කාමරයට ඇතුළු වන්නේ නම්, හෝටල් ආරක්ෂක කාර්ය මණ්ඩලය එසේ නොවේ ඔබව හොර රහසේ අල්ලා ගැනීම අවශ්‍ය . ඔබ ඔවුන් සමඟ ගිවිසුමක් ඇති කර නොගත්තේ “මම නැවත මගේ ඇතුළට යාමට උත්සාහ කළහොත් කාමරයට පසුව, ඔබ මාව නවත්වන්න අවශ්‍යයි. ඒ වෙනුවට, ඔබ ඔවුන් සමඟ ගිවිසුමක් අත්සන් කළ අතර, “මම පසුව මගේ කාමරයට නොයන බවට පොරොන්දු වෙමි”, ඔබ කඩ කළ ගිවිසුමක් .

මෙම තත්වය තුළ ඕනෑම දෙයක් සිදුවිය හැකිය . පොත එහි තිබිය හැකිය - ඔබ වාසනාවන්තයි. වෙනත් කෙනෙකුගේ පොතක් එහි තිබිය හැකි අතර ඔබේ හෝටලයේ උදුනෙහි තිබිය හැකිය. ඔබ ඇතුළට එන විට ඔබේ පොත කැබලිවලට ඉරා දැමිය හැකිය. හෝටලයට මේසය සහ පොත් සම්පූර්ණයෙන්ම ඉවත් කර එය වෙනුවට ඇඳුම් ආයිත්තම් කට්ටලයක් ආදේශ කළ හැකිය. මුළු හෝටලයම කඩා දමා පාපන්දු ක්‍රීඩාංගනයක් වෙනුවට විය හැකි අතර, ඔබ වටේට හොරෙන් යන අතරතුර පිපිරුමකින් ඔබ මිය යනු ඇත.

සිදුවන්නේ කුමක්දැයි ඔබ දන්නේ නැත; ඔබ හෝටල් ක් පරීක්ෂා හා නීති විරෝධී ලෙස පසුව පාවිච්චි කිරීම සඳහා ප්රධාන සොරකම් විට, ඔබ නිසා අනාවැකි හැකි, ආරක්ෂිත ලෝකයේ ජීවත් වීමට අයිතිය අත්හැර ඔබ පද්ධතියේ නීති බිඳ දැමීම සඳහා තෝරා ගත්තේය.

C ++ ආරක්ෂිත භාෂාවක් නොවේ . එය පද්ධතියේ නීති කඩ කිරීමට සතුටු සිතින් ඔබට ඉඩ සලසයි. ඔබට අවසර නැති කාමරයකට ගොස් නැවත එහි නොසිටින මේසයක් හරහා කටකතා පෑම වැනි නීති විරෝධී හා මෝඩ දෙයක් කිරීමට ඔබ උත්සාහ කරන්නේ නම්, C ++ ඔබව නවත්වන්නේ නැත. C ++ ට වඩා ආරක්ෂිත භාෂාවන් ඔබගේ බලය සීමා කිරීමෙන් මෙම ගැටළුව විසඳයි - උදාහරණයක් ලෙස යතුරු මත දැඩි පාලනයක් තබා ගැනීමෙන්.

යාවත්කාලීන කරන්න

ශුද්ධ වූ යහපත්කම, මෙම පිළිතුර විශාල අවධානයක් ලබා ගනී. (ඒ මන්දැයි මට විශ්වාස නැත - මම එය "විනෝදජනක" කුඩා ප්‍රතිසමයක් ලෙස සලකමි, නමුත් කුමක් වුවත්.)

තවත් තාක්ෂණික සිතුවිලි කිහිපයක් සමඟ මෙය ටිකක් යාවත්කාලීන කිරීම ජර්මානු විය හැකි යැයි මම සිතුවෙමි.

සම්පාදකයින් එම වැඩසටහන මඟින් හසුරුවන ලද දත්ත ගබඩා කිරීම කළමනාකරණය කරන කේත ජනනය කිරීමේ ව්‍යාපාරයේ යෙදී සිටිති. මතකය කළමනාකරණය කිරීම සඳහා කේත ජනනය කිරීමේ විවිධ ක්‍රම රාශියක් ඇත, නමුත් කාලයත් සමඟ මූලික තාක්ෂණික ක්‍රම දෙකක් මුල් බැස තිබේ.

පළමුවැන්න නම්, ගබඩාවේ එක් එක් බයිටයේ "ජීවිත කාලය" - එනම් යම් වැඩසටහන් විචල්‍යයක් සමඟ වලංගු ලෙස සම්බන්ධ වී ඇති කාල සීමාව - යම් ආකාරයක "දිගුකාලීන" ගබඩා ප්‍රදේශයක් තිබීමයි. කාලය. සම්පාදකයා විසින් "ගොඩවල් කළමණාකරුවෙකු" වෙත ඇමතුම් ජනනය කරන අතර එය අවශ්‍ය විටෙක ගබඩා කිරීම ගතිකව වෙන් කරන්නේ කෙසේදැයි දන්නා අතර එය තවදුරටත් අවශ්‍ය නොවන විට එය නැවත ලබා ගනී.

දෙවන ක්‍රමය නම්, එක් එක් බයිටයේ ආයු කාලය හොඳින් දන්නා “කෙටි කාලීන” ගබඩා ප්‍රදේශයක් තිබීමයි. මෙන්න, ජීවිත කාලය “කූඩු” රටාවක් අනුගමනය කරයි. මෙම කෙටිකාලීන විචල්‍යයන්ගෙන් දීර්-කාලීනව වෙනත් කෙටි කාලීන විචල්‍යයන්ට පෙර වෙන් කරනු ලබන අතර එය අවසන් වරට නිදහස් වනු ඇත. කෙටි කාලීන විචල්‍යයන් දීර්-කාලයක් ජීවත් වූ පසු වෙන් කරනු ලබන අතර ඒවා ඉදිරියේ නිදහස් වනු ඇත. මෙම කෙටි කාලීන විචල්‍යයන්ගේ ආයු කාලය දීර් ed කාලයක් ජීවත් වන අයගේ ජීවිත කාලය තුළ “කැදැල්ල” වේ.

දේශීය විචල්යයන් පසු රටාව අනුගමනය කරයි; ක්‍රමයක් ඇතුළත් කළ විට, එහි දේශීය විචල්‍යයන් සජීවීව පැමිණේ. එම ක්‍රමය වෙනත් ක්‍රමයක් ලෙස හැඳින්වූ විට, නව ක්‍රමයේ දේශීය විචල්‍යයන් සජීවීව පැමිණේ. පළමු ක්‍රමයේ දේශීය විචල්‍යයන් මිය යාමට පෙර ඔවුන් මිය යනු ඇත. දේශීය විචල්‍යයන් හා සම්බන්ධ ගබඩා වල ආයු කාලය ආරම්භයේ හා අවසානයෙහි සාපේක්ෂ අනුපිළිවෙල කලින් කලට සකස් කළ හැකිය.

මේ හේතුව නිසා, දේශීය විචල්‍යයන් සාමාන්‍යයෙන් "තොග" දත්ත ව්‍යුහයක් මත ගබඩා කිරීමක් ලෙස ජනනය වේ, මන්ද යත්, තොගයක් එහි ඇති දේ මත ඇති බැවින් එය මතට තල්ලු කරන ලද පළමු දෙය අවසන් වරට ඉවත් වනු ඇත.

එය හරියට හෝටලය අනුපිළිවෙලින් කාමර කුලියට ගැනීමට පමණක් තීරණය කරන අතර, ඔබ පරීක්ෂා කර බැලීමට වඩා කාමර අංකයක් ඇති සෑම කෙනෙකුටම ඔබට පරීක්ෂා කළ නොහැක.

ඒ නිසා අපි තොගය ගැන සිතමු. බොහෝ මෙහෙයුම් පද්ධති වලදී ඔබට එක් නූලකට එක් තොගයක් ලැබෙන අතර තොගය නිශ්චිත ස්ථාවර ප්‍රමාණයක් ලෙස වෙන් කරනු ලැබේ. ඔබ ක්‍රමයක් අමතන විට, දේවල් තොගයට තල්ලු කරනු ලැබේ. මුල් පෝස්ටරය මෙහි දැක්වෙන පරිදි, ඔබ ඔබේ ක්‍රමයෙන් බැහැරව නැවත තොගයට යොමු කළහොත්, එය සම්පූර්ණයෙන්ම වලංගු මිලියනයක බයිට් මතක කොටසක මැදට යොමු කිරීමකි. අපගේ ප්‍රතිසමයට අනුව, ඔබ හෝටලයෙන් පිටතට යන්න; ඔබ එසේ කරන විට, ඔබ වැඩිම සංඛ්‍යාවක් වාඩිලාගෙන සිටින කාමරයෙන් පිටව ගියේය. ඔබ පසුපස වෙනත් කිසිවෙකු පරික්ෂා නොකරන්නේ නම් සහ ඔබ නීතිවිරෝධී ලෙස නැවත ඔබේ කාමරයට ගියහොත්, ඔබගේ සියලු දේ මෙම විශේෂිත හෝටලයේ තවමත් පවතින බවට සහතික වේ .

තාවකාලික වෙළඳසැල් සඳහා අපි තොග භාවිතා කරන්නේ ඒවා ඇත්තෙන්ම ලාභදායී සහ පහසු බැවිනි. ප්‍රදේශවාසීන් ගබඩා කිරීම සඳහා තොගයක් භාවිතා කිරීම සඳහා C ++ ක්‍රියාත්මක කිරීම අවශ්‍ය නොවේ; එයට ගොඩවල් භාවිතා කළ හැකිය. එය එසේ නොවේ, මන්ද එය වැඩසටහන මන්දගාමී වනු ඇත.

C ++ ක්‍රියාවට නැංවීම සඳහා ඔබ ඉතිරි කර ඇති කුණු කසළ ඉවත් නොකිරීමට අවශ්‍ය වන අතර එමඟින් ඔබට පසුව නීති විරෝධී ලෙස ඒ සඳහා නැවත පැමිණිය හැකිය. ඔබ දැන් ඉවත්ව ගිය "කාමරයේ" ඇති සෑම දෙයක්ම ශුන්‍යයට හැරෙන කේතයක් සම්පාදනය කිරීම සම්පාදකයාට සම්පූර්ණයෙන්ම නීතිමය ය. එය නැවත මිල අධික වනු ඇති නිසා නොවේ.

තොගය තාර්කිකව හැකිලෙන විට, වලංගු වූ ලිපින තවමත් මතකයේ සිතියම් ගත කර ඇති බව සහතික කිරීම සඳහා C ++ ක්‍රියාත්මක කිරීම අවශ්‍ය නොවේ. ක්‍රියාත්මක කිරීමේ ක්‍රියාවලියට මෙහෙයුම් පද්ධතියට පැවසීමට අවසර දී ඇත "අපි දැන් මෙම තොගයේ පිටුව භාවිතා කර ඇත්තෙමු. මා වෙනත් ආකාරයකින් පවසන තුරු, කිසිවෙකු කලින් වලංගු වූ තොග පිටුවට අත තැබුවහොත් ක්‍රියාවලිය විනාශ කරන ව්‍යතිරේකයක් නිකුත් කරන්න". නැවතත්, ක්‍රියාවට නැංවීම ඇත්ත වශයෙන්ම එසේ නොකරන්නේ එය මන්දගාමී හා අනවශ්‍ය නිසාය.

ඒ වෙනුවට, ක්‍රියාත්මක කිරීම මඟින් ඔබට වැරදි කිරීමට සහ එයින් ගැලවීමට ඉඩ ලබා දේ. ගොඩක් වෙලාවට. එක් දිනක් සැබවින්ම භයානක දෙයක් වැරදී ගොස් ක්‍රියාවලිය පුපුරා යයි.

මෙය ගැටළු සහගතය. නීති රාශියක් ඇති අතර ඒවා අහම්බෙන් බිඳ දැමීම ඉතා පහසුය. මට නිසැකවම බොහෝ වාර ගණනක් තිබේ. වඩාත් නරක දෙය නම්, ගැටළුව බොහෝ විට මතු වන්නේ දූෂණය සිදුවීමෙන් පසු නැනෝ තත්පර බිලියන ගණනක් දූෂිත බව මතකය අනාවරණය වූ විට පමණි, එය අවුල් කළේ කවුරුන්ද යන්න සොයා ගැනීම ඉතා අසීරු වූ විට පමණි.

ඔබගේ බලය සීමා කිරීමෙන් වැඩි මතක ආරක්ෂිත භාෂා මෙම ගැටළුව විසඳයි. "සාමාන්‍ය" සී # හි හුදෙක් දේශීයයෙකුගේ ලිපිනය ගෙන එය ආපසු ලබා දීමට හෝ පසුව ගබඩා කිරීමට ක්‍රමයක් නොමැත. ඔබට දේශීයයෙකුගේ ලිපිනය ගත හැකිය, නමුත් භාෂාව දක්ෂ ලෙස නිර්මාණය කර ඇති අතර එමඟින් දේශීය අරමුණු වල ආයු කාලය අවසන් වූ පසු එය භාවිතා කළ නොහැක. දේශීය ලිපිනය ගෙන එය නැවත සමත් කිරීම සඳහා, ඔබ විශේෂ "අනාරක්ෂිත" ලෙස සම්පාදකවරයා දමා ඇති, හා ඔබේ වැඩසටහන "අනාරක්ෂිත" යන වචනය දමා, ඔබට මීට කරන්නේ බව අවධානය යොමු කිරීමට කිරීමට නීති කඩ කළ හැකි භයානක දෙයක්.

වැඩිදුර කියවීම සඳහා:

  • නැවත යොමු කිරීම් සඳහා C # ඉඩ දුන්නේ නම් කුමක් කළ යුතුද? අහම්බෙන් එය අද බ්ලොග් සටහනේ මාතෘකාව වේ:

    https://ericlippert.com/2011/06/23/ref-returns-and-ref-locals/

  • මතකය කළමනාකරණය කිරීම සඳහා අප තොග භාවිතා කරන්නේ ඇයි? C # හි අගය වර්ග සෑම විටම තොගයේ ගබඩා කර තිබේද? අතථ්‍ය මතකය ක්‍රියා කරන්නේ කෙසේද? C # මතක කළමනාකරු ක්‍රියා කරන ආකාරය පිළිබඳ තවත් බොහෝ මාතෘකා. මෙම ලිපි බොහොමයක් සී ++ ක්‍රමලේඛකයන්ට ද ජර්මනිය වේ:

    https://ericlippert.com/tag/memory-management/


57
untmuntoo: අවාසනාවකට එය අථත්‍ය මතකයේ පිටුවක් දිරාපත් වීමට හෝ ඉවත් කිරීමට පෙර මෙහෙයුම් පද්ධතිය අනතුරු ඇඟවීමේ සයිරන් හ like ක් මෙන් නොවේ. ඔබ එය තවදුරටත් අයිති කර නොගත් විට ඔබ එම මතකය සමඟ පොරබදන්නේ නම්, ඔබ ඉවත් කළ පිටුවක් ස්පර්ශ කරන විට සමස්ත ක්‍රියාවලියම ඉවත් කර ගැනීමට මෙහෙයුම් පද්ධතිය එහි අයිතිවාසිකම් තුළ පරිපූර්ණ වේ. උත්පාතය!
එරික් ලිපර්ට්

85
Yle කයිල්: එය කරන්නේ ආරක්ෂිත හෝටල් පමණි. ක්‍රමලේඛන යතුරු සඳහා කාලය නාස්ති නොකිරීමෙන් අනාරක්ෂිත හෝටල්වලට මැනිය හැකි ලාභයක් ලැබේ.
ඇලෙක්සැන්ඩර් ටෝස්ට්ලිං

503
@cyberguijarro: C ++ මතකය ආරක්ෂිත නොවන බව සත්‍යයකි. එය කිසිවක් "පහර" නොවේ. උදාහරණයක් ලෙස, "සී ++ යනු අස්ථාවර, භයානක මතක ආකෘතියක් මත ගොඩ ගසා ඇති අඩු, අධික ලෙස සංකීර්ණ අංගයන්ගෙන් යුත් බිහිසුණු මිෂ්මාෂ් එකක් වන අතර මගේ සිහිබුද්ධිය වෙනුවෙන් මම තවදුරටත් එහි වැඩ නොකරන සෑම දිනකම මම ස්තූතිවන්ත වෙමි", එය C ++ ට පහර දෙයි. එය මතකය ආරක්ෂිත නොවන බව පෙන්වා දීමෙන් මුල් පෝස්ටරය මෙම ගැටළුව දකින්නේ මන්ද යන්න පැහැදිලි කරයි; එය කතුවැකිය නොව ප්‍රශ්නයට පිළිතුරු සපයයි.
එරික් ලිපර්ට්

51
නිශ්චිතවම කිවහොත්, හෝටලයේ පිළිගැනීමේ නිලධාරියා ඔබ සමඟ යතුර රැගෙන යාම ගැන සෑහීමකට පත් වූ බව සඳහන් කළ යුතුය. "ඔහ්, මම මේ යතුර මා සමඟ ගත්තොත් ඔබට කමක් නැද්ද?" "ඉදිරියට යන්න. ඇයි මම සැලකිලිමත් වන්නේ? මම මෙහි වැඩ කරන්නේ". ඔබ එය භාවිතා කිරීමට උත්සාහ කරන තුරු එය නීති විරෝධී නොවේ.
philsquared

140
කරුණාකර, කරුණාකර අවම වශයෙන් දිනක් පොතක් ලිවීම ගැන සලකා බලන්න. එය සංශෝධිත හා පුළුල් කළ බ්ලොග් සටහන් එකතුවක් වුවද මම එය මිලදී ගන්නෙමි, එසේම බොහෝ අය එසේ කරනු ඇතැයි මට විශ්වාසයි. නමුත් විවිධ ක්‍රමලේඛන ආශ්‍රිත කරුණු පිළිබඳ ඔබේ මුල් සිතුවිලි සහිත පොතක් හොඳ කියවීමක් වනු ඇත. ඒ සඳහා කාලය සොයා ගැනීම ඇදහිය නොහැකි තරම් දුෂ්කර බව මම දනිමි, නමුත් කරුණාකර එකක් ලිවීම ගැන සලකා බලන්න.
Dyppl

277

ඔබ මෙතන කරන්නේ, හුදෙක් මතකය කියවීම හා ලිවීම සඳහා භාවිතා ලිපිනය විය a. දැන් ඔබ පිටත සිටින විට foo, එය අහඹු මතක ප්‍රදේශයකට යොමු කිරීමක් පමණි. එය එසේ වන්නේ ඔබේ උදාහරණයේ දී එම මතක ප්‍රදේශය පවතින අතර වෙන කිසිවක් මේ මොහොතේ එය භාවිතා නොකරයි. එය දිගටම භාවිතා කිරීමෙන් ඔබ කිසිවක් බිඳ දමන්නේ නැත, වෙන කිසිවක් තවම එය නැවත ලියා නැත. එමනිසා, 5එය තවමත් පවතී. සැබෑ වැඩසටහනක දී, එම මතකය වහාම පාහේ නැවත භාවිතා වන අතර ඔබ මෙය කිරීමෙන් යමක් බිඳ දමනු ඇත (බොහෝ කලකට පසුව රෝග ලක්ෂණ නොපෙන්වයි!)

ඔබ නැවත පැමිණෙන විට foo, ඔබ මෙහෙයුම් පද්ධතියට පවසන්නේ ඔබ තවදුරටත් එම මතකය භාවිතා නොකරන බවත් එය වෙනත් දෙයකට නැවත පැවරිය හැකි බවත්ය. ඔබ වාසනාවන්ත නම් සහ එය කිසි විටෙකත් නැවත පවරා නොගන්නේ නම් සහ මෙහෙයුම් පද්ධතිය නැවත එය භාවිතා නොකරන්නේ නම්, එවිට ඔබ බොරුවෙන් මිදෙනු ඇත. සමහරවිට ඔබ එම ලිපිනයෙන් අවසන් වන ඕනෑම දෙයක් ලිවීමට ඉඩ ඇත.

සම්පාදකයා පැමිණිලි නොකරන්නේ මන්දැයි දැන් ඔබ කල්පනා කරන්නේ නම්, එය fooප්‍රශස්තිකරණයෙන් ඉවත් වී ඇති නිසා විය හැකිය . එය සාමාන්‍යයෙන් මේ ආකාරයේ දෙයක් ගැන ඔබට අනතුරු අඟවයි. සී ඔබ උපකල්පනය කරන්නේ ඔබ කරන්නේ කුමක්ද යන්න සහ තාක්‍ෂණිකව ඔබ මෙහි විෂය පථය උල්ලං have නය කර නොමැති බවයි ( aපිටත තමා ගැන සඳහනක් නොමැත foo), මතක ප්‍රවේශ නීති පමණක් වන අතර එය දෝෂයකට වඩා අනතුරු ඇඟවීමක් අවුලුවයි.

කෙටියෙන්: මෙය සාමාන්‍යයෙන් ක්‍රියාත්මක නොවනු ඇත, නමුත් සමහර විට අහම්බෙන් සිදු වේ.


152

ගබඩා අවකාශය තවම අඩාල වී නැති නිසා. එම හැසිරීම ගණන් නොගන්න.


1
මිනිසා, "සත්‍යය යනු කුමක්ද? පිලාත් විහිළුවට ලක් කරමින් කීවේය." සමහර විට එය එම හෝටල් ලාච්චුවේ ගිඩියොන්ගේ බයිබලය විය හැකිය. කෙසේ වෙතත් ඔවුන්ට සිදු වූයේ කුමක්ද? අවම වශයෙන් ලන්ඩනයේ ඔවුන් තවදුරටත් නොමැති බව සැලකිල්ලට ගන්න. සමානාත්මතා නීතිය යටතේ ඔබට ආගමික පත්‍රිකා පුස්තකාලයක් අවශ්‍ය වනු ඇතැයි මම සිතමි.
රොබ් කෙන්ට්

බොහෝ කලකට පෙර මා ලියා ඇති බවට දිවුරුම් දීමට මට හැකිය, නමුත් එය මෑතකදී මතු වූ අතර මගේ ප්‍රතිචාරය එහි නොමැති බව මට පෙනී ගියේය. දැන් මට ඔබගේ යෝජනා ඉහත සඳහන් කර ගත යුතුය. මා බලාපොරොත්තු වන පරිදි මම විනෝදයට පත් වනු ඇත>. <
msw

1
හාහා. බ්‍රිතාන්‍යයේ ශ්‍රේෂ් greatest තම රචකයෙකු වන ෆ්‍රැන්සිස් බේකන්, ෂේක්ස්පියර්ගේ නාට්‍ය ලියා ඇතැයි සමහරු සැක කරති, මන්ද යත්, රටක ව්‍යාකරණ පාසල් ළමයෙකු, ග්ලෝවර් පුතෙකු, දක්ෂයෙකු විය හැකි බව ඔවුන්ට පිළිගත නොහැකි බැවිනි. ඉංග්‍රීසි පන්ති ක්‍රමය එයයි. 'මම සත්‍යයයි' කියා යේසුස් පැවසුවා. oregonstate.edu/instruct/phl302/text/bacon/bacon_essays.html
රොබ් කෙන්ට්

84

සියලුම පිළිතුරු සඳහා කුඩා එකතු කිරීමක්:

ඔබ එවැනි දෙයක් කරන්නේ නම්:

#include<stdio.h>
#include <stdlib.h>
int * foo(){
    int a = 5;
    return &a;
}
void boo(){
    int a = 7;

}
int main(){
    int * p = foo();
    boo();
    printf("%d\n",*p);
}

ප්‍රතිදානය බොහෝ විට වනු ඇත: 7

එයට හේතුව foo () වෙතින් ආපසු පැමිණි පසු තොගය නිදහස් කර නැවත boo () විසින් නැවත භාවිතා කිරීමයි. ඔබ ක්‍රියාත්මක කළ හැකි දේ ඉවත් කළහොත් ඔබට එය පැහැදිලිව පෙනෙනු ඇත.


2
යටින් පවතින සිරස් න්‍යාය අවබෝධ කර ගැනීම සඳහා සරල, නමුත් විශිෂ්ට උදාහරණයකි. “Int a = 5;” යනුවෙන් ප්‍රකාශ කරමින් එක් පරීක්ෂණ එකතු කිරීමක් කරන්න. foo () හි "ස්ථිතික int a = 5;" ස්ථිතික විචල්‍යයක විෂය පථය සහ ආයු කාලය අවබෝධ කර ගැනීමට භාවිතා කළ හැකිය.
පාලනය

15
-1 "සඳහා 7 ක් වනු ඇත ". සම්පාදකයා විසින් බූ එකක් ලියාපදිංචි කළ හැකිය. එය අනවශ්‍ය නිසා එය ඉවත් කිරීමට ඉඩ ඇත. * P 5 ක් නොවීමට හොඳ අවස්ථාවක් තිබේ , නමුත් එයින් අදහස් කරන්නේ එය 7 ක් වීමට හොඳ හේතුවක් ඇති බවයි .
මතෙ

2
එය නිර්වචනය නොකළ හැසිරීම ලෙස හැඳින්වේ!
ෆ්‍රැන්සිස් කූග්ලර්

ඇයි සහ කෙසේද booතොගය නැවත භාවිතා කරන්නේ foo? ක්‍රියාකාරී කොටස් එකිනෙකෙන් වෙන් වී නැති අතර, මෙම කේතය විෂුවල් ස්ටුඩියෝ 2015 හි ක්‍රියාත්මක වන කුණු කසළ මට ලැබේ
ampawd

1
@ampawd එය වසරකට ආසන්නය, නමුත් නැත, "ශ්‍රිත කොටස්" එකිනෙකාගෙන් වෙන් නොකෙරේ. CONTEXT හි තොගයක් ඇත. එම සන්දර්භය එහි තොගය ප්‍රධාන වශයෙන් ඇතුල් කිරීමට භාවිතා කරයි, පසුව බැස යයි foo(), පවතී, පසුව බැස යයි boo(). Foo()හා Boo()දෙකම එකම ස්ථානයක දී අඩුක්කුව පහිටුම් දක්වනය සමග ඇතුල් කරන්න. කෙසේ වෙතත් මෙය රඳා පැවතිය යුතු හැසිරීම නොවේ. වෙනත් 'දේවල්' (බාධා කිරීම් හෝ මෙහෙයුම් පද්ධතිය වැනි) ඇමතුම් boo()සහ foo()එහි අන්තර්ගතය වෙනස් කිරීම අතර තොගය භාවිතා කළ හැකිය ...
රුස් ෂුල්ට්ස්

72

C ++ හි, ඔබට ඕනෑම ලිපිනයකට පිවිසිය හැකිය , නමුත් එයින් අදහස් කරන්නේ ඔබ එසේ කළ යුතු බවයි. ඔබ ප්‍රවේශ වන ලිපිනය තවදුරටත් වලංගු නොවේ. එය ක්‍රියාත්මක වන්නේ foo නැවත පැමිණීමෙන් පසුව වෙනත් කිසිවක් මතකය සීරීමට ලක් කළ නමුත් එය බොහෝ තත්වයන් යටතේ බිඳ වැටිය හැකි බැවිනි. Valgrind සමඟ ඔබේ වැඩසටහන විශ්ලේෂණය කිරීමට උත්සාහ කරන්න , නැතහොත් එය ප්‍රශස්තිකරණය කර සම්පාදනය කරන්න, සහ බලන්න ...


5
ඔබ බොහෝ විට අදහස් කරන්නේ ඔබට ඕනෑම ලිපිනයකට ප්‍රවේශ වීමට උත්සාහ කළ හැකි බවයි. අද බොහෝ මෙහෙයුම් පද්ධති කිසිදු වැඩසටහනකට කිසිදු ලිපිනයකට ප්‍රවේශ වීමට ඉඩ නොදෙන නිසා; ලිපින අවකාශය ආරක්ෂා කිරීම සඳහා ආරක්ෂිත ටොන් ගණනක් ඇත. මේ නිසා තවත් LOADLIN.EXE එකක් නොතිබෙනු ඇත.
v010dya

67

අවලංගු මතකයට ප්‍රවේශ වීමෙන් ඔබ කිසි විටෙකත් C ++ ව්‍යතිරේකයක් විසි නොකරයි. අත්තනෝමතික මතක ස්ථානයක් සඳහන් කිරීමේ පොදු අදහසට ඔබ උදාහරණයක් සපයයි. මට මේ වගේ දෙයක් කරන්න පුළුවන්:

unsigned int q = 123456;

*(double*)(q) = 1.2;

මෙන්න මම සරලවම 123456 ද්විත්ව ලිපිනය ලෙස සලකන අතර එයට ලියන්න. ඕනෑම දෙයක් සිදුවිය හැකිය:

  1. qඇත්ත වශයෙන්ම ද්විත්ව වලංගු ලිපිනයක් විය හැකිය, උදා double p; q = &p;.
  2. q වෙන් කළ මතකය තුළ කොතැනක හෝ යොමු විය හැකි අතර මම එහි බයිට් 8 ක් නැවත ලියමි.
  3. q වෙන් කරන ලද මතකයෙන් පිටත ලකුණු සහ මෙහෙයුම් පද්ධතියේ මතක කළමනාකරු මගේ වැඩසටහනට ඛණ්ඩනය කිරීමේ දෝෂ සං signal ාවක් යවන අතර එමඟින් ධාවන කාලය එය අවසන් වේ.
  4. ඔබ ලොතරැයිය දිනයි.

ඔබ එය සකසන ආකාරය නැවත ලබා දුන් ලිපිනය වලංගු මතක ප්‍රදේශයක් වෙත යොමු කිරීම තරමක් සාධාරණ ය, මන්ද යත් එය තොගයට මඳක් down තින් විය හැකි නමුත් එය තවමත් ඔබට අවලංගු ස්ථානයකි නිර්ණායක විලාසිතා.

සාමාන්‍ය වැඩසටහන් ක්‍රියාත්මක කිරීමේදී ඔබ වැනි මතක ලිපිනවල අර්ථකථන වලංගු භාවය කිසිවෙකු ස්වයංක්‍රීයව පරීක්ෂා නොකරනු ඇත. කෙසේ වෙතත්, මතක නිදොස්කරණය valgrindකරන්නෙකු මෙය සතුටින් කරනු ඇත, එබැවින් ඔබ එය හරහා ඔබේ වැඩසටහන ක්‍රියාත්මක කර දෝෂ දැක ගත යුතුය.


9
මම දැන් වැඩසටහනක් ලිවීමට යන්නේ මෙම වැඩසටහන දිගටම කරගෙන යන නිසාය4) I win the lottery
අයිඩියාකාපි

29

සක්‍රීය කර ඇති ප්‍රශස්තකරණය සමඟ ඔබ ඔබේ වැඩසටහන සම්පාදනය කළාද? එමfoo() කාර්යය ඉතා සරල වන අතර එහි ප්රතිඵලයක් කේතය දී inlined හෝ ආදේශ කර ඇති.

නමුත් මාක් බී සමඟ එකඟ වන්නේ එහි ප්‍රති behavior ලයක් ලෙස හැසිරීම නිර්වචනය කර නොමැති බවයි.


ඒක තමයි මගේ ඔට්ටුව. ප්‍රශස්තිකරණය මඟින් ක්‍රියාකාරී ඇමතුම ඉවත් කරන ලදි.
එරික් ඇරොනෙස්ටි

9
එය අවශ්‍ය නොවේ. Foo () ට පසුව නව ශ්‍රිතයක් කැඳවනු නොලබන බැවින්, දේශීය සිරස් රාමුවේ කාර්යයන් තවමත් නැවත ලියනු නොලැබේ. Foo () ට පසුව තවත් ශ්‍රිත ආයාචනයක් එක් කරන්න, 5එවිට එය වෙනස් වනු ඇත ...
ටොමාස්

මම GCC 4.8 සමඟ වැඩසටහන ක්‍රියාත්මක කළ අතර, කෝට් වෙනුවට printf (සහ stdio ද ඇතුළුව) ආදේශ කළෙමි. නිවැරදිව අනතුරු අඟවයි "අනතුරු ඇඟවීම: දේශීය විචල්යයේ ලිපිනය 'a' ආපසු [-Wreturn-local-addr]". නිමැවුම් 58 ප්‍රශස්තිකරණයකින් තොරව සහ 08 -O3 සමඟ. පුදුමයට කරුණක් නම් P හි අගය 0 ක් වුවද එහි ලිපිනය ඇත. මම බලාපොරොත්තු වූයේ NULL (0) ලිපිනය ලෙස ය.
kevinf

23

ඔබේ ගැටලුවට විෂය පථයට කිසිදු සම්බන්ධයක් නැත . ඔබ පෙන්වන කේතයේ, ශ්‍රිතය ශ්‍රිතයේ mainනම් නොපෙනේ foo, එබැවින් ඔබට පිටතින් මෙම නම aසමඟ කෙලින්ම foo වෙත පිවිසිය නොහැක .foo

ඔබට ඇති ගැටළුව වන්නේ නීති විරෝධී මතකය සඳහන් කිරීමේදී වැඩසටහන දෝෂයක් සං signal ා නොකරන්නේ මන්ද යන්නයි. මෙයට හේතුව C ++ ප්‍රමිතීන් නීති විරෝධී මතකය සහ නෛතික මතකය අතර ඉතා පැහැදිලි සීමාවක් නියම නොකිරීමයි. පිටතට පැමිණි තොගයේ යමක් සඳහන් කිරීම සමහර විට දෝෂ ඇති වන අතර සමහර විට එසේ නොවේ. එය රඳා පවතියි. මෙම හැසිරීම ගැන නොසිතන්න. ඔබ ක්‍රමලේඛනය කරන විට එය සැමවිටම දෝෂයක් ඇති කරයි යැයි උපකල්පනය කරන්න, නමුත් ඔබ එය නිදොස් කිරීමේදී කිසි විටෙකත් දෝෂයක් සං signal ා නොකරනු ඇතැයි උපකල්පනය කරන්න.


IBM සඳහා වූ ටර්බෝ සී ක්‍රමලේඛනයේ පැරණි පිටපතකින් මට මතකයි , ග්‍රැෆික් මතකය කෙලින්ම හසුරුවන්නේ කෙසේද, සහ අයිබීඑම් හි පෙළ මාදිලියේ වීඩියෝ මතකයේ සැකැස්ම ඉතා විස්තරාත්මකව විස්තර කරන විට මම යම් ආකාරයකින් ආපසු සෙල්ලම් කළෙමි. ඇත්ත වශයෙන්ම, කේතය ක්‍රියාත්මක වූ පද්ධතිය මඟින් එම ලිපිනවලට ලිවීම යන්නෙන් අදහස් කරන්නේ කුමක්ද යන්න පැහැදිලිව අර්ථ දක්වා ඇත, එබැවින් ඔබ වෙනත් පද්ධතිවලට අතේ ගෙන යා හැකි ආකාරය ගැන කරදර නොවූ තාක් කල් සියල්ල හොඳින් විය. IIRC, අවලංගු කිරීමේ කරුණු එම පොතේ පොදු තේමාවක් විය.
CVn

Ic මයිකල් කෝර්ලිං: ෂුවර්! මිනිසුන් වරකට වරක් අපිරිසිදු වැඩක් කිරීමට කැමතියි;)
චැං පෙන්

18

ඔබ දැන් මතක ලිපිනයක් යවයි, එයට අවසර දී ඇති නමුත් බොහෝ විට දෝෂයකි.

ඔව්, ඔබ එම මතක ලිපිනය අවලංගු කිරීමට උත්සාහ කළහොත් ඔබට නිර්වචනය නොකළ හැසිරීමක් ඇත.

int * ref () {

 int tmp = 100;
 return &tmp;
}

int main () {

 int * a = ref();
 //Up until this point there is defined results
 //You can even print the address returned
 // but yes probably a bug

 cout << *a << endl;//Undefined results
}

මම එකඟ නොවෙමි: ඊට පෙර ගැටලුවක් තිබේ cout. *aවෙන් නොකළ (නිදහස්) මතකය වෙත යොමු කරයි. ඔබ එය නොසලකා හැරියත්, එය තවමත් භයානකයි (හා බොහෝ විට ව්‍යාජ).
ereOn

@ereOn: ගැටලුව මගින් මා අදහස් කළ දේ මම වඩාත් පැහැදිලි කළෙමි, නමුත් වලංගු c ++ කේතය අනුව එය භයානක නොවේ. නමුත් පරිශීලකයා වැරැද්දක් කර ඇති අතර එය නරක දෙයක් කරනු ඇත. සමහර විට නිදසුනක් ලෙස ඔබ තොගය වර්ධනය වන ආකාරය බැලීමට උත්සාහ කරන අතර ඔබ ලිපින වටිනාකම ගැන පමණක් සැලකිලිමත් වන අතර එය කිසි විටෙකත් අවතක්සේරු නොකරනු ඇත.
බ්‍රයන් ආර්. බොන්ඩි

18

එය දින දෙකකට පෙර මෙහි සාකච්ඡා කර ඇති සම්භාව්‍ය නිර්වචනය නොකළ හැසිරීමකි - වෙබ් අඩවිය වටා ටිකක් සොයන්න. කෙටියෙන් කිවහොත්, ඔබ වාසනාවන්ත විය, නමුත් ඕනෑම දෙයක් සිදුවිය හැකි අතර ඔබේ කේතය මතකයට අවලංගු ප්‍රවේශයක් ලබා දෙයි.


18

ඇලෙක්ස් පෙන්වා දුන් පරිදි මෙම හැසිරීම නිර්වචනය කර නැත - ඇත්ත වශයෙන්ම, බොහෝ සම්පාදකයින් මෙය කිරීමට එරෙහිව අනතුරු අඟවනු ඇත, මන්ද එය බිඳ වැටීම් ලබා ගැනීමට පහසු ක්‍රමයක් වන බැවිනි.

ඔබට ලැබිය හැකි භයානක හැසිරීම පිළිබඳ උදාහරණයක් සඳහා, මෙම නියැදිය උත්සාහ කරන්න:

int *a()
{
   int x = 5;
   return &x;
}

void b( int *c )
{
   int y = 29;
   *c = 123;
   cout << "y=" << y << endl;
}

int main()
{
   b( a() );
   return 0;
}

මෙය "y = 123" මුද්‍රණය කරයි, නමුත් ඔබේ ප්‍රති results ල වෙනස් විය හැකිය (ඇත්තටම!). ඔබේ දර්ශකය වෙනත්, සම්බන්ධයක් නැති දේශීය විචල්‍යයන් සමඟ සම්බන්ධ වේ.


18

සියලු අනතුරු ඇඟවීම් කෙරෙහි අවධානය යොමු කරන්න. දෝෂ පමණක් විසඳන්න එපා.
GCC මෙම අවවාදය පෙන්වයි

අවවාදයයි: දේශීය විචල්යයේ ලිපිනය 'a' ආපසු

මෙය C ++ හි බලයයි. ඔබ මතකය ගැන සැලකිලිමත් විය යුතුය. -Werrorධජය සමඟ , මෙම අනතුරු ඇඟවීම දෝෂයක් වන අතර දැන් ඔබට එය නිදොස්කරණය කළ යුතුය.


17

එය ක්‍රියාත්මක වන්නේ එහි තැන්පත් කළ දින සිට (තවමත්) තොගය වෙනස් කර නොමැති බැවිනි. aනැවත පිවිසීමට පෙර තවත් කාර්යයන් කිහිපයක් අමතන්න (ඒවා වෙනත් කාර්යයන් ද අමතයි) එවිට ඔබ තවදුරටත් එතරම් වාසනාවන්ත නොවනු ඇත ... ;-)


16

ඔබ සැබවින්ම නිර්වචනය නොකළ හැසිරීමට යොමු විය.

තාවකාලික කෘතියක ලිපිනය නැවත ලබා දීම, නමුත් ශ්‍රිතයක් අවසානයේ තාවකාලිකයන් විනාශ වන බැවින් ඒවාට ප්‍රවේශ වීමේ ප්‍රති results ල නිර්වචනය නොකෙරේ.

එබැවින් ඔබ වෙනස් නොකළ aනමුත් aවරක් තිබූ මතක ස්ථානය වෙනස් විය. මෙම වෙනස කඩා වැටීම හා බිඳ වැටීම අතර වෙනසට බෙහෙවින් සමාන ය.


14

සාමාන්ය සම්පාදක නිර්මාණයන්, ඔබ "බව සහජීවනය, සමඟ මතක වාරණ වටිනාකම මුද්රණය ලෙස කේතය සිතිය හැකි විය කිරීම සඳහා භාවිතා විසින් අත්පත්". එසේම, ඔබ දේශීයව අඩංගු ශ්‍රිතයකට නව ශ්‍රිත ආයාචනයක් එක් කළහොත් intඑය a(හෝ මතක ලිපිනයෙහි අගය) ලැබීමට හොඳ අවස්ථාවක්a පෙන්වා දීමට භාවිතා . මෙය සිදු වන්නේ විවිධ දත්ත අඩංගු නව රාමුවක් සමඟ තොගය නැවත ලියනු ලබන බැවිනි.

කෙසේ වෙතත්, මෙය නිර්වචනය නොකළ හැසිරීමක් වන අතර ඔබ එය වැඩ කිරීමට විශ්වාසය නොතැබිය යුතුය!


3
"ඒ ලිපිනය සමඟ මතක වාරණ වටිනාකම මුද්රණය කිරීමට යොදා හරි නොවේ විසින් තමයි අත්පත්". මෙය ඔහුගේ කේතයට මනාව අර්ථ දක්වා ඇති අර්ථයක් ඇති බවක් පෙනේ, එය එසේ නොවේ. බොහෝ සම්පාදකයින් එය ක්‍රියාත්මක කරන්නේ කෙසේ ද යන්න ඔබ නිවැරදිය.
බ්‍රෙනන් වින්සන්ට්

Ren බ්‍රෙනන් වින්සන්ට්: ගබඩාව වාඩිලාගෙන සිටියදී a, දර්ශකය එහි ලිපිනය තබා ගත්තේය a. ඔවුන්ගේ ඉලක්කයේ ආයු කාලය අවසන් වූ පසු ක්‍රියාත්මක කිරීම් මඟින් ලිපින වල හැසිරීම නිර්වචනය කිරීම ප්‍රමිතියට අවශ්‍ය නොවුනත්, සමහර වේදිකාවල UB සැකසී ඇත්තේ පරිසරයේ ලක්ෂණයක් ලෙස ලේඛනගතව ය. දේශීය විචල්‍යයක ලිපිනය විෂය පථයෙන් බැහැර වූ පසු සාමාන්‍යයෙන් එතරම් ප්‍රයෝජනවත් නොවනු ඇතත්, වෙනත් ඉලක්ක ලිපින ඔවුන්ගේ ජීවිතවල ජීවිත කාලයෙන් පසුවද අර්ථවත් විය හැකිය.
සුපර් කැට්

Ren බ්‍රෙනන් වින්සන්ට්: නිදසුනක් ලෙස, සම්මතයට reallocප්‍රතිලාභ අගයට සාපේක්ෂව දර්ශකයක් සංසන්දනය කිරීමට ඉඩ දිය යුතු යැයි සම්මතයට අවශ්‍ය නොවිය හැකි අතර, පැරණි බ්ලොක් තුළ ඇති ලිපිනවලට නව එකක් වෙත යොමු කිරීම සඳහා සකස් කිරීමට ඉඩ නොදෙන අතර සමහර ක්‍රියාත්මක කිරීම් එසේ කරයි , සහ එවැනි අංගයක් ගසාකන කේතය කිසිදු ක්‍රියාවක් වළක්වා ගත යුතු කේතයට වඩා කාර්යක්ෂම විය හැකිය - සැසඳීම් පවා - ලබා දී ඇති ප්‍රතිපාදන සඳහා දර්ශකයන් සම්බන්ධ කිරීම realloc.
සුපර් කැට්

14

එයට හැකි වන්නේ, aඑහි විෂය පථයේ ( fooශ්‍රිතයේ) ආයු කාලය සඳහා තාවකාලිකව වෙන් කරන ලද විචල්‍යයකි . ඔබ fooමතකයෙන් ආපසු පැමිණි පසු නොමිලේ වන අතර නැවත ලිවිය හැකිය.

ඔබ කරන්නේ කුමක්ද යන්න නිර්වචනය නොකළ හැසිරීමක් ලෙස විස්තර කෙරේ . ප්‍රති result ලය අනාවැකි කිව නොහැක.


12

ඔබ :: printf භාවිතා කළත් නිවැරදිව (?) කොන්සෝල ප්‍රතිදානය සහිත දේවල් විශාල ලෙස වෙනස් විය හැකිය. පහත කේතය තුළ ඔබට නිදොස්කරණය සමඟ සෙල්ලම් කළ හැකිය (x86, 32-bit, MSVisual Studio හි පරීක්ෂා කර ඇත):

char* foo() 
{
  char buf[10];
  ::strcpy(buf, "TEST”);
  return buf;
}

int main() 
{
  char* s = foo();    //place breakpoint & check 's' varialbe here
  ::printf("%s\n", s); 
}

5

ශ්‍රිතයකින් ආපසු පැමිණි පසු, මතක ස්ථානයක තබා ඇති අගයන් වෙනුවට සියලු හඳුනාගැනීම් විනාශ වන අතර අපට හඳුනාගැනීමක් නොමැතිව අගයන් සොයාගත නොහැක. නමුත් එම ස්ථානයේ පෙර ශ්‍රිතය මඟින් ගබඩා කර ඇති අගය තවමත් අඩංගු වේ.

ඒ නිසා, මෙහි ක්රියාව foo()ලිපිනය ආපසු පැමිනෙමින් aහා aඑහි ලිපිනය පැමිණි පසු විනාශ කර ඇත. නැවත ලබා දුන් ලිපිනය හරහා ඔබට වෙනස් කළ අගයට ප්‍රවේශ විය හැකිය.

මට සැබෑ ලෝක ආදර්ශයක් ගැනීමට ඉඩ දෙන්න:

මිනිසෙකු යම් ස්ථානයක මුදල් සඟවා ඔබට ස්ථානය කියයි යැයි සිතමු. ටික වේලාවකට පසු, ඔබට මුදල් ස්ථානය පැවසූ පුද්ගලයා මිය යයි. නමුත් තවමත් ඔබට එම සැඟවුණු මුදල් සඳහා ප්‍රවේශය ඇත.


4

මතක ලිපින භාවිතා කිරීමේ 'අපිරිසිදු' ක්‍රමය එයයි. ඔබ ලිපිනයක් (දර්ශකය) ආපසු ලබා දෙන විට එය ශ්‍රිතයක දේශීය විෂය පථයට අයත් දැයි ඔබ නොදනී. එය ලිපිනයක් පමණි. දැන් ඔබ 'foo' ශ්‍රිතය ක්‍රියාත්මක කළ විට, 'a' හි එම ලිපිනය (මතක ස්ථානය) දැනටමත් ඔබගේ යෙදුමේ (ක්‍රියාවලියේ) ආමන්ත්‍රණය කළ හැකි මතකයේ (ආරක්ෂිතව, අවම වශයෙන්) වෙන් කර ඇත. 'Foo' ශ්‍රිතය ආපසු පැමිණි පසු, 'a' හි ලිපිනය 'අපිරිසිදු' ලෙස සැලකිය හැකි නමුත් එය එහි තිබේ, පිරිසිදු නොකෙරේ, හෝ වැඩසටහනේ වෙනත් කොටසක ප්‍රකාශන මගින් බාධා / වෙනස් කර නොමැත (මෙම විශේෂිත අවස්ථාවෙහිදී අවම වශයෙන්). AC / C ++ සම්පාදකයා එවැනි 'අපිරිසිදු' ප්‍රවේශයකින් ඔබව වළක්වන්නේ නැත (ඔබ සැලකිලිමත් නම් ඔබට අනතුරු අඟවනු ඇත).


1

ඔබේ කේතය ඉතා අවදානම්. ඔබ දේශීය විචල්‍යයක් නිර්මාණය කරමින් සිටී (ක්‍රියාකාරීත්වය අවසන් වූ පසු එය විනාශ වී යයි සලකනු ලැබේ) සහ එම විචල්‍යය විනාශ වූ පසු ඔබ එය මතකයේ ලිපිනය යවයි.

එයින් අදහස් වන්නේ මතක ලිපිනය වලංගු විය හැකි හෝ නොවිය හැකි අතර ඔබේ කේතය විය හැකි මතක ලිපින ගැටළු වලට ගොදුරු විය හැකි ය (නිදසුනක් ලෙස ඛණ්ඩනය කිරීමේ දෝෂය).

මෙයින් අදහස් කරන්නේ ඔබ ඉතා නරක දෙයක් කරන බවයි, ඔබ මතක ලිපිනයක් දර්ශකය වෙත යවන බව විශ්වාස කරන්න.

ඒ වෙනුවට මෙම උදාහරණය සලකා බලා එය පරීක්ෂා කරන්න:

int * foo()
{
   int *x = new int;
   *x = 5;
   return x;
}

int main()
{
    int* p = foo();
    std::cout << *p << "\n"; //better to put a new-line in the output, IMO
    *p = 8;
    std::cout << *p;
    delete p;
    return 0;
}

ඔබේ උදාහරණය මෙන් නොව, මෙම උදාහරණය සමඟ ඔබ:

  • දේශීය ශ්‍රිතයකට int සඳහා මතකය වෙන් කිරීම
  • ශ්‍රිතය කල් ඉකුත් වූ විටත් එම මතක ලිපිනය තවමත් වලංගු වේ (එය කිසිවෙකු විසින් මකා නොදමනු ඇත)
  • මතක ලිපිනය විශ්වාසදායකය (එම මතක කොටස නොමිලේ ලෙස නොසැලකේ, එබැවින් එය මකා දමන තුරු එය ඉක්මවා නොයනු ඇත)
  • භාවිතා නොකරන විට මතක ලිපිනය මකා දැමිය යුතුය. (වැඩසටහන අවසානයේ මකාදැමීම බලන්න)

පවතින පිළිතුරු වලින් දැනටමත් ආවරණය නොවන දෙයක් ඔබ එකතු කළාද? කරුණාකර අමු දර්ශක භාවිතා නොකරන්න / new.
කක්ෂයේ සැහැල්ලු ධාවන තරඟ

1
අසන්නා අමු දර්ශක භාවිතා කළේය. විශ්වාසදායක දර්ශකය සහ විශ්වාසදායකයා අතර වෙනස දැකීමට ඔහුට ඉඩ දීම සඳහා ඔහු කළ ආදර්ශය හරියටම පිළිබිඹු කරන උදාහරණයක් මම කළෙමි. ඇත්ත වශයෙන්ම මගේ හා සමාන තවත් පිළිතුරක් ඇත, නමුත් එය භාවිතා කරන්නේ strcpy wich, IMHO, නවක භාවිතා කරන මගේ උදාහරණයට වඩා නවක කෝඩරයකට පැහැදිලි නොවිය හැකිය.
නොබුන්

ඔවුන් පාවිච්චි කළේ නැහැ new. ඔබ ඔවුන්ට භාවිතා කිරීමට උගන්වයි new. නමුත් ඔබ භාවිතා නොකළ යුතුය new.
කක්ෂයේ සැහැල්ලු ධාවන තරඟ

එබැවින් ඔබේ මතය අනුව ඇත්ත වශයෙන්ම මතකය වෙන් කිරීමට වඩා ශ්‍රිතයක් තුළ දේශීය විචල්‍යයක් වෙත ලිපිනයක් යැවීම වඩා හොඳද? මෙය තේරුමක් නැත. ප්‍රධාන වශයෙන් ඔබ දර්ශකයන් ගැන විමසන්නේ නම් (ඉල්ලුම්කරු නව, නමුත් භාවිතා කළ දර්ශක භාවිතා කළේ නැත).
නොබුන්

මම එය කීවේ කවදාද? නැත, යොමු කරන ලද සම්පතේ හිමිකාරිත්වය නිසි ලෙස දැක්වීමට ස්මාර්ට් පොයින්ටර් භාවිතා කිරීම වඩා හොඳය. new2019 දී භාවිතා නොකරන්න (ඔබ පුස්තකාල කේතය ලියන්නේ නැත්නම්) සහ නවකයන්ට එසේ කිරීමට උගන්වන්න එපා! චියර්ස්.
කක්ෂයේ සැහැල්ලු ධාවන තරඟ
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.