আমি কেন একই স্ট্রাক্টে একটি মান এবং সেই মানটির একটি রেফারেন্স সঞ্চয় করতে পারি না?


222

আমার একটি মান আছে এবং আমি সেই মানটি এবং সেই মানের ভিতরে থাকা কোনও কিছুর একটি উল্লেখ আমার নিজস্ব ধরণের মধ্যে সঞ্চয় করতে চাই:

struct Thing {
    count: u32,
}

struct Combined<'a>(Thing, &'a u32);

fn make_combined<'a>() -> Combined<'a> {
    let thing = Thing { count: 42 };

    Combined(thing, &thing.count)
}

কখনও কখনও, আমার একটি মান আছে এবং আমি সেই মানটি এবং একই মানটিতে সেই মানটির একটি রেফারেন্স সঞ্চয় করতে চাই:

struct Combined<'a>(Thing, &'a Thing);

fn make_combined<'a>() -> Combined<'a> {
    let thing = Thing::new();

    Combined(thing, &thing)
}

কখনও কখনও, আমি এমনকি মানটির একটি রেফারেন্সও নিচ্ছি না এবং আমি একই ত্রুটি পেয়েছি:

struct Combined<'a>(Parent, Child<'a>);

fn make_combined<'a>() -> Combined<'a> {
    let parent = Parent::new();
    let child = parent.child();

    Combined(parent, child)
}

এই প্রতিটি ক্ষেত্রেই আমি একটি ত্রুটি পেয়েছি যে মানগুলির মধ্যে একটি "যথেষ্ট দিন বেঁচে না"। এই সমস্যার মানে কি?


1
পরবর্তী উদাহরণের জন্য, একটি সংজ্ঞা Parentএবং Childসহায়তা করতে পারে ...
ম্যাথিউ মিঃ

1
@MatthieuM। আমি এটি নিয়ে বিতর্ক করেছি, তবে দুটি সংযুক্ত প্রশ্নের ভিত্তিতে এটির বিরুদ্ধে সিদ্ধান্ত নিয়েছি। এই প্রশ্নগুলির কোনওটিরই কাঠামোর সংজ্ঞা বা প্রশ্নে থাকা পদ্ধতির দিকে নজর দেওয়া হয়নি , তাই আমি ভেবেছিলাম যে নকল করা ভাল হবে যে লোকেরা আরও সহজেই এই প্রশ্নটিকে নিজের অবস্থার সাথে মেলে দিতে পারে। নোট আমি যে কি করতে উত্তর পদ্ধতি স্বাক্ষর প্রদর্শন করুন।
শেপমাস্টার

উত্তর:


244

এর একটি সাধারণ বাস্তবায়ন দেখুন :

struct Parent {
    count: u32,
}

struct Child<'a> {
    parent: &'a Parent,
}

struct Combined<'a> {
    parent: Parent,
    child: Child<'a>,
}

impl<'a> Combined<'a> {
    fn new() -> Self {
        let parent = Parent { count: 42 };
        let child = Child { parent: &parent };

        Combined { parent, child }
    }
}

fn main() {}

এটি ত্রুটির সাথে ব্যর্থ হবে:

error[E0515]: cannot return value referencing local variable `parent`
  --> src/main.rs:19:9
   |
17 |         let child = Child { parent: &parent };
   |                                     ------- `parent` is borrowed here
18 | 
19 |         Combined { parent, child }
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function

error[E0505]: cannot move out of `parent` because it is borrowed
  --> src/main.rs:19:20
   |
14 | impl<'a> Combined<'a> {
   |      -- lifetime `'a` defined here
...
17 |         let child = Child { parent: &parent };
   |                                     ------- borrow of `parent` occurs here
18 | 
19 |         Combined { parent, child }
   |         -----------^^^^^^---------
   |         |          |
   |         |          move out of `parent` occurs here
   |         returning this value requires that `parent` is borrowed for `'a`

এই ত্রুটিটি পুরোপুরি বুঝতে, আপনাকে ভাবতে হবে যে কীভাবে মানগুলি মেমরিতে উপস্থাপিত হয় এবং আপনি যখন এই মানগুলি স্থানান্তর করেন তখন কী ঘটে । আসুন Combined::newকিছু অনুমানমূলক মেমরি ঠিকানা দিয়ে টীকায়িত করুন যা দেখায় যে মানগুলি কোথায় রয়েছে:

let parent = Parent { count: 42 };
// `parent` lives at address 0x1000 and takes up 4 bytes
// The value of `parent` is 42 
let child = Child { parent: &parent };
// `child` lives at address 0x1010 and takes up 4 bytes
// The value of `child` is 0x1000

Combined { parent, child }
// The return value lives at address 0x2000 and takes up 8 bytes
// `parent` is moved to 0x2000
// `child` is ... ?

কি হবে child? মানটি যদি ঠিক সেইভাবে স্থানান্তরিত parent হয়, তবে এটি মেমরিটিকে উল্লেখ করবে যে এতে আর একটি বৈধ মান থাকার গ্যারান্টি নেই। কোডের অন্য কোনও অংশে মেমরি ঠিকানার 0x1000 এ মান সংরক্ষণের অনুমতি দেওয়া হয়। এটি একটি পূর্ণসংখ্যা হিসাবে ধরে নেওয়া স্মৃতিতে অ্যাক্সেস করা ক্র্যাশ এবং / অথবা সুরক্ষা বাগের দিকে নিয়ে যেতে পারে এবং মরচে প্রতিরোধকারী ত্রুটির অন্যতম প্রধান বিষয়।

এটি হ'ল সমস্যাটি যা আজীবন প্রতিরোধ করে। একটি জীবনকাল হ'ল কিছুটা মেটাডেটা যা আপনাকে এবং সংকলকটিকে এটির বর্তমান মেমরির স্থানে কতক্ষণ মান কার্যকর হবে তা জানার অনুমতি দেয় । এটি একটি গুরুত্বপূর্ণ পার্থক্য, কারণ এটি মরচে আগতদের একটি সাধারণ ভুল। মরিচা লাইফটাইম কোনও সময় তৈরির সময় নয় যখন কোনও বস্তু তৈরি হয় এবং কখন এটি ধ্বংস হয়!

সাদৃশ্য হিসাবে, এটিকে এভাবে ভাবুন: কোনও ব্যক্তির জীবনের সময় এগুলি অনেকগুলি পৃথক স্থানে বাস করবে, যার প্রত্যেকটির একটি আলাদা ঠিকানা থাকবে with একটি মরিয়া জীবনকাল আপনি বর্তমানে যে ঠিকানাটিতে রয়েছেন তার সাথে সম্পর্কিত, ভবিষ্যতে আপনি কখনই মারা যাবেন তা নিয়ে নয় (যদিও মৃত্যুবরণও আপনার ঠিকানা পরিবর্তন করে)। প্রতিবার আপনি সরানোর সময় এটি প্রাসঙ্গিক কারণ আপনার ঠিকানাটি আর বৈধ নয়।

এটাও গুরুত্বপূর্ণ যে জীবনকাল আপনার কোড পরিবর্তন করে না ; আপনার কোডটি লাইফটাইমগুলি নিয়ন্ত্রণ করে, আপনার লাইফটাইম কোডটি নিয়ন্ত্রণ করে না। করুণ কথায় হ'ল "জীবনকাল বর্ণনামূলক, প্রেসক্রিপটিভ নয়"।

আসুন Combined::newআমরা কয়েকটি লাইনের নম্বর দিয়ে টীকাযুক্ত করি যা আমরা লাইফ টাইম হাইলাইট করতে ব্যবহার করব:

{                                          // 0
    let parent = Parent { count: 42 };     // 1
    let child = Child { parent: &parent }; // 2
                                           // 3
    Combined { parent, child }             // 4
}                                          // 5

কংক্রিট জীবদ্দশায় এর parent1 থেকে 4 হয়, সমেত (যা আমি প্রতিনিধিত্ব করব [1,4])। এর কংক্রিট জীবনকাল childহয় [2,4], এবং বিনিময়ে মূল্যের কংক্রিট জীবনকাল হয় [4,5]। শূন্য থেকে শুরু হওয়া কংক্রিট লাইফটাইমগুলি পাওয়া সম্ভব - যা কোনও ক্রিয়াকলাপ বা ব্লকের বাইরে থাকা কিছুতে প্যারামিটারের আজীবন প্রতিনিধিত্ব করবে।

মনে রাখবেন যে, এর জীবদ্দশায় childনিজেই [2,4], কিন্তু যে এটা বোঝায় একটি জীবনকাল সঙ্গে একটি মান [1,4]। রেফার-টু মানটি করার আগে যতক্ষণ রেফারিং মানটি অবৈধ হয়ে যায় এটি ঠিক আছে fine সমস্যাটি তখন ঘটে যখন আমরা childব্লক থেকে ফিরে আসার চেষ্টা করি । এটি তার প্রাকৃতিক দৈর্ঘ্যের বাইরে জীবনকালকে "অতিরিক্ত-প্রসারিত" করবে।

এই নতুন জ্ঞানের প্রথম দুটি উদাহরণ ব্যাখ্যা করা উচিত। তৃতীয়টির বাস্তবায়নের দিকে তাকাতে হবে Parent::child। সম্ভাবনাগুলি হ'ল এটি দেখতে এরকম কিছু দেখাবে:

impl Parent {
    fn child(&self) -> Child { /* ... */ }
}

সুস্পষ্ট জেনেরিক আজীবন প্যারামিটারগুলি লেখা এড়াতে এটি আজীবন এলিজেন ব্যবহার করে । এটি সমান:

impl Parent {
    fn child<'a>(&'a self) -> Child<'a> { /* ... */ }
}

উভয় ক্ষেত্রেই, পদ্ধতিটি বলে যে একটি Childকাঠামো ফিরে আসবে যা কংক্রিটের আজীবন প্যারামিটারাইজড ছিল self। অন্যভাবে বলা হয়েছে, Childউদাহরণটিতে Parentএটি তৈরি করা হয়েছে এমন একটি উল্লেখ রয়েছে এবং এটি Parentউদাহরণের চেয়ে বেশি দিন বাঁচতে পারে না ।

এটি আমাদের সনাক্ত করতে দেয় যে আমাদের তৈরির কার্যক্রমে কিছু সত্যই ভুল:

fn make_combined<'a>() -> Combined<'a> { /* ... */ }

যদিও আপনি এই লিখিতটিকে অন্য কোনও আকারে দেখার সম্ভাবনা বেশি:

impl<'a> Combined<'a> {
    fn new() -> Combined<'a> { /* ... */ }
}

উভয় ক্ষেত্রেই কোনও আর্গুমেন্টের মাধ্যমে কোনও আজীবন প্যারামিটার সরবরাহ করা হচ্ছে না। এর অর্থ হ'ল আজীবন যা Combinedপ্যারামিটারাইজ করা হবে তা কোনও কিছুর দ্বারা সীমাবদ্ধ নয় - কলার এটি যা চায় তা হতে পারে। এটি অযৌক্তিক, কারণ কলার 'staticআজীবন নির্দিষ্ট করে দিতে পারে এবং এই শর্তটি পূরণ করার কোনও উপায় নেই।

আমি কীভাবে এটি ঠিক করব?

সবচেয়ে সহজ এবং সর্বাধিক প্রস্তাবিত সমাধান হ'ল এই আইটেমগুলিকে একই কাঠামোয় একসাথে রাখার চেষ্টা না করা। এটি করে আপনার কাঠামো বাসা বাঁধাই আপনার কোডের লাইফটাইমকে নকল করবে। এক সাথে কাঠামোর মধ্যে ডেটার মালিক এমন প্রকারগুলি রাখুন এবং তারপরে এমন পদ্ধতিগুলি সরবরাহ করুন যা আপনাকে প্রয়োজনীয় হিসাবে রেফারেন্স যুক্ত রেফারেন্স বা অবজেক্টগুলি পেতে দেয়।

একটি বিশেষ ক্ষেত্রে রয়েছে যেখানে আজীবন ট্র্যাকিং অত্যধিক alousর্ষান্বিত হয়: যখন আপনার স্তূপে কিছু রাখা হয়। Box<T>উদাহরণস্বরূপ আপনি যখন এটি ব্যবহার করেন এটি ঘটে । এই ক্ষেত্রে, যে কাঠামোটি সরানো হয় তাতে গাদা মধ্যে একটি পয়েন্টার থাকে। পয়েন্ট-এ মানটি স্থিতিশীল থাকবে তবে পয়েন্টারের ঠিকানাটি নিজেই সরে যাবে। অনুশীলনে, এটি কোনও ব্যাপার নয়, আপনি সর্বদা পয়েন্টারটি অনুসরণ করেন।

ভাড়া বাক্স (আর পরিচালিত বা সমর্থিত) বা owning_ref বাক্স এই ক্ষেত্রে প্রতিনিধিত্ব উপায় আছে, কিন্তু তারা প্রয়োজন যে বেস ঠিকানা সরাতে না । এটি মিউটেশন ভেক্টরগুলিকে বাতিল করে দেয়, যার ফলে পুনরায় স্থান নির্ধারণ এবং হিপ-বরাদ্দ মানগুলির সরানো হতে পারে।

ভাড়া নিয়ে সমস্যার সমাধানের উদাহরণ:

অন্যান্য ক্ষেত্রে, আপনি কোনও প্রকারের রেফারেন্স-কাউন্টিংয়ে যেতে চান, যেমন ব্যবহার করে Rcবা Arc

অধিক তথ্য

parentস্ট্রাক্টে স্থানান্তরিত হওয়ার পরে , সংকলক কেন নতুন কাঠামোর সাথে parentএটি উল্লেখ করতে এবং childস্ট্রাক্টে এটি নির্ধারণ করতে সক্ষম হয় না?

তাত্ত্বিকভাবে এটি করা সম্ভব হলেও এটি করা বিপুল পরিমাণ জটিলতা এবং ওভারহেডের পরিচয় দেয়। প্রতিবার অবজেক্টটি সরানো হয়েছে, সংকলকটির রেফারেন্সটি "ফিক্স আপ" করতে কোড inোকানো দরকার। এর অর্থ হ'ল স্ট্রাক্ট অনুলিপি করা এখন খুব সস্তা অপারেশন নয় যা কিছু বিটকে সরিয়ে দেয়। এমনকি এটির অর্থ এইও হতে পারে যে এই জাতীয় কোডটি ব্যয়বহুল, একটি অনুমানমূলক অপ্টিমাইজারটি কতটা ভাল হবে তার উপর নির্ভর করে:

let a = Object::new();
let b = a;
let c = b;

এটি প্রতিটি পদক্ষেপের জন্য ঘটতে বাধ্য করার পরিবর্তে প্রোগ্রামার চয়ন করতে সক্ষম হয় যে কখন এমন পদ্ধতি তৈরি করে যখন আপনি তাদের ডাকবেন তখন উপযুক্ত রেফারেন্স নেবে by

নিজেই একটি রেফারেন্স সহ একটি টাইপ

একটি নির্দিষ্ট ক্ষেত্রে রয়েছে যেখানে আপনি নিজের প্রসঙ্গে একটি প্রকার তৈরি করতে পারেনOptionএটি দুটি ধাপে তৈরি করার মতো আপনাকে এমন কিছু ব্যবহার করতে হবে যদিও:

#[derive(Debug)]
struct WhatAboutThis<'a> {
    name: String,
    nickname: Option<&'a str>,
}

fn main() {
    let mut tricky = WhatAboutThis {
        name: "Annabelle".to_string(),
        nickname: None,
    };
    tricky.nickname = Some(&tricky.name[..4]);

    println!("{:?}", tricky);
}

এটি কিছুটা অর্থে কাজ করে তবে তৈরি মানটি সীমাবদ্ধ - এটি কখনই সরানো যায় না। উল্লেখযোগ্যভাবে, এর অর্থ এটি কোনও ফাংশন থেকে ফিরে পাওয়া যায় না বা কোনও কিছুর কাছে মূল্য-দিয়ে দেওয়া যায় না। একটি কনস্ট্রাক্টর ফাংশন লাইফটাইমগুলির সাথে উপরের মতো একই সমস্যা দেখায়:

fn creator<'a>() -> WhatAboutThis<'a> { /* ... */ }

কি হবে Pin?

Pin, মরিচা 1.33 এ স্থিতিশীল, মডিউল ডকুমেন্টেশনে এটি রয়েছে :

এই জাতীয় দৃশ্যের একটি প্রধান উদাহরণ স্ব-রেফারেন্টিয়াল স্ট্রাক্ট তৈরি করা হবে, যেহেতু পয়েন্টারযুক্ত কোনও বস্তুটিকে নিজের দিকে সরানো এগুলি অকার্যকর করে দেবে, যা অপরিবর্তিত আচরণের কারণ হতে পারে।

এটি উল্লেখ করা গুরুত্বপূর্ণ যে "স্ব-রেফারেন্টিয়াল" এর অর্থ রেফারেন্স ব্যবহার করা আবশ্যক নয় । প্রকৃতপক্ষে, একটি স্ব-রেফারেন্টিয়াল কাঠামোর উদাহরণটি সুনির্দিষ্টভাবে বলেছে (জোর দেওয়া খনি):

আমরা এই সম্পর্কে কমলারটিকে সাধারণ রেফারেন্স সহ অবহিত করতে পারি না, যেহেতু সাধারণ theণ নেওয়ার নিয়ম দিয়ে এই ধরণটি বর্ণনা করা যায় না। পরিবর্তে আমরা একটি কাঁচা পয়েন্টার ব্যবহার করি , যদিও এটি একটি নাল নয় বলে পরিচিত, যেহেতু আমরা জানি যে এটি স্ট্রিংয়ের দিকে নির্দেশ করছে।

এই আচরণের জন্য একটি কাঁচা পয়েন্টার ব্যবহার করার ক্ষমতা মরিচা 1.0 থেকে বিদ্যমান। প্রকৃতপক্ষে, মালিকানা-রেফ এবং ভাড়া হুডের নীচে কাঁচা পয়েন্টার ব্যবহার।

Pinটেবিলের সাথে যুক্ত হওয়া একমাত্র জিনিস হ'ল একটি সাধারণ উপায় যে প্রদত্ত মানটি স্থানান্তরিত না হওয়ার গ্যারান্টিযুক্ত।

আরো দেখুন:


1
এর মতো কিছু (যেমন. gd / wl2IAt ) কি মূর্তিমান হিসাবে বিবেচিত? অর্থাত, কাঁচা ডেটার পরিবর্তে পদ্ধতিগুলির মাধ্যমে ডেটা প্রকাশ করা।
পিটার হল

2
@ পিটারহাল নিশ্চিত, এর অর্থ হ'ল Combinedমালিকানাধীন Childযার মালিকানা রয়েছে Parent। আপনার আসল ধরণের উপর নির্ভর করে এটি বোধগম্য হতে পারে বা নাও পারে। আপনার নিজের অভ্যন্তরীণ ডেটাতে রেফারেন্সগুলি ফিরিয়ে দেওয়া বেশ সাধারণ।
শেপমাস্টার

গাদা সমস্যার সমাধান কী?
derekdreery

@derekdreery সম্ভবত আপনি আপনার মন্তব্যটি প্রসারিত করতে পারেন? কেন সম্পূর্ণ প্যারাগ্রাফটি নিজস্ব_আরফের ক্রেটের বিষয়ে অপ্রতুল কথা বলছে ?
শেপমাস্টার

1
@ ফিনবেকার এখনও রেফারেন্স এবং সেই রেফারেন্সের মান সঞ্চয় করা অসম্ভব । Pinস্ব-রেফারেন্সিয়াল পয়েন্টারযুক্ত কোনও কাঠামোর সুরক্ষা জানার বেশিরভাগ উপায় । একই উদ্দেশ্যে কাঁচা পয়েন্টার ব্যবহারের ক্ষমতাটি মরিচা 1.0 থেকে বিদ্যমান।
শেপমাস্টার

4

একটি সামান্য পৃথক ইস্যু যার ফলে খুব অনুরূপ সংকলক বার্তাগুলি ঘটে তার একটি স্পষ্ট উল্লেখ উল্লেখের পরিবর্তে বস্তুর আজীবন নির্ভরতা। এর উদাহরণ ssh2 গ্রন্থাগার। যখন কিছু একটি পরীক্ষা প্রকল্পের চেয়ে বড় উন্নয়নশীল, এটা করা চেষ্টা প্রলুব্ধকর হয় Sessionএবং Channelএকটি struct মধ্যে একে অপরের পাশাপাশি যে সেশন থেকে পাওয়া ব্যবহারকারী থেকে বাস্তবায়ন বিবরণ গোপন। যাইহোক, নোট করুন যে Channelসংজ্ঞাটির 'sessটাইপ টীকাতে জীবনকাল রয়েছে, যদিও Sessionতা নেই।

এটি লাইফটাইম সম্পর্কিত অনুরূপ সংকলক ত্রুটির কারণ ঘটায়।

একে একে খুব সহজ উপায়ে সমাধান করার একটি উপায় হ'ল Sessionকলারের বাইরে বাইরের ঘোষণা করা এবং তারপরে স্ট্রাক্টের মধ্যে রেফারেন্সটি আজীবন সহকারে এনটেট করা, এই জাস্ট ইউজার ফোরামের পোস্টে একই ইস্যুতে এসএফটিপি অন্তর্ভুক্ত করার সময় উত্তরটির অনুরূপ post । এটি মার্জিত দেখায় না এবং সর্বদা প্রয়োগ নাও হতে পারে - কারণ এখন আপনার কাছে দুটি চেয়ে সত্ত্বা রয়েছে যা আপনি চেয়েছিলেন!

ভাড়া ক্রেট বা অন্য উত্তর থেকে মালিকানা_আরফ ক্রেট দেখা যাচ্ছে এই সমস্যার সমাধানও। এর owning_ref, যা এই সঠিক উদ্দেশ্যে বিশেষ বস্তু রয়েছে বিবেচনা করা যাক: OwningHandle। অন্তর্নিহিত অবজেক্টটি সরানো এড়াতে, আমরা এটিকে একটি ব্যবহার করে গাদাতে বরাদ্দ করি Boxযা আমাদের নিম্নলিখিত সম্ভাব্য সমাধান দেয়:

use ssh2::{Channel, Error, Session};
use std::net::TcpStream;

use owning_ref::OwningHandle;

struct DeviceSSHConnection {
    tcp: TcpStream,
    channel: OwningHandle<Box<Session>, Box<Channel<'static>>>,
}

impl DeviceSSHConnection {
    fn new(targ: &str, c_user: &str, c_pass: &str) -> Self {
        use std::net::TcpStream;
        let mut session = Session::new().unwrap();
        let mut tcp = TcpStream::connect(targ).unwrap();

        session.handshake(&tcp).unwrap();
        session.set_timeout(5000);
        session.userauth_password(c_user, c_pass).unwrap();

        let mut sess = Box::new(session);
        let mut oref = OwningHandle::new_with_fn(
            sess,
            unsafe { |x| Box::new((*x).channel_session().unwrap()) },
        );

        oref.shell().unwrap();
        let ret = DeviceSSHConnection {
            tcp: tcp,
            channel: oref,
        };
        ret
    }
}

এই কোডটির ফলাফল হ'ল আমরা Sessionআর ব্যবহার করতে পারি না , তবে এটি Channelব্যবহার করব আমরা এটির পাশাপাশি সংরক্ষণ করা হয়। কারণ OwningHandleঅবজেক্টটি ডিপ্রিফারেন্সের সাথে সম্পর্কিত হয় Box, যা Channelকোনও স্ট্রাক্টে স্টোর করার সময় , এটির নাম দেয় we দ্রষ্টব্য: এটি আমার বোঝাপড়া মাত্র। আমার সন্দেহ আছে যে এটি সঠিক নাও হতে পারে, যেহেতু এটি অনর্থক আলোচনারOwningHandle খুব কাছাকাছি বলে মনে হয় ।

এখানে একটি কৌতূহলোদ্দীপক বিবরণ হ'ল Sessionযুক্তিযুক্তভাবে TcpStreamযেমন ছিল তেমন সম্পর্ক Channelরয়েছে Sessionতবুও এর মালিকানা নেওয়া হয় নি এবং এটি করার জন্য কোনও ধরণের টিকা নেই। পরিবর্তে, এটি হ্যান্ডশেক পদ্ধতির ডকুমেন্টেশন হিসাবে এটি যত্ন নেওয়া ব্যবহারকারীর উপর নির্ভর করে :

এই অধিবেশনটি প্রদত্ত সকেটের মালিকানা গ্রহণ করে না, যোগাযোগটি সঠিকভাবে সম্পাদিত হয়েছে কিনা তা নিশ্চিত করার জন্য সকেটটি এই অধিবেশনটির আজীবন ধরে রাখবে তা নিশ্চিত করার পরামর্শ দেওয়া হয়।

প্রোটোকলটিতে হস্তক্ষেপ হতে পারে বলে প্রদত্ত স্ট্রিমটি এই অধিবেশনটির সময়কালের জন্য একই সাথে অন্য কোথাও ব্যবহার করা হয় না বলেও সুপারিশ করা হয়।

সুতরাং TcpStreamব্যবহারের সাথে কোডের যথার্থতা নিশ্চিত করার জন্য প্রোগ্রামার সম্পূর্ণরূপে। এর সাথে OwningHandle, unsafe {}ব্লকটি ব্যবহার করে যেখানে "বিপজ্জনক যাদু" ঘটে তার দিকে দৃষ্টি আকর্ষণ করা হয় ।

এই ইস্যুটির আরও একটি আরও উচ্চ-স্তরের আলোচনা এই মরিচা ব্যবহারকারীর ফোরাম থ্রেডে রয়েছে - যার মধ্যে একটি আলাদা উদাহরণ এবং ভাড়া ক্রেট ব্যবহার করে এর সমাধান অন্তর্ভুক্ত রয়েছে, এতে অনিরাপদ ব্লক নেই।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.